:::

直接執行Python腳本:Python Caller / Running a Python Script Directly in Windows: Python Caller

image

繼前一篇的RScript Caller之後,這次要來介紹的是直接執行Python的Python Caller。這隻程式的主要目的是提供讓Python腳本檔案(副檔名為.py)直接關聯到Python-Caller.exe,這樣就能在檔案總管中點兩下直接執行,然後在執行完畢後暫停,讓開發者可以看看執行結果。以下就是Python Caller的下載、設定與使用介紹。因為做法跟RScript Caller蠻像的,所以兩篇內容會看起來很像就是了。


下載 / Download

2018-02-11_193051

image

下載後直接解壓縮即可。

image

這邊我們會用到以下兩個檔案:

  • Python-Caller.exe 主程式,要讓Python腳本 (副檔名為.py) 關聯到這個主程式。
  • config.ini 設定檔,設定Python環境的路徑。

設定 / Configuration

要使用Python-Caller.exe的話,要先設定config.ini中Python環境的路徑,然後再將Python腳本(副檔名為.py)關聯到Python-Caller.exe主程式。以下我們就來看看怎麼做吧。

設定檔 / config.ini

2018-02-11_194704

請用文字編輯器開啟config.ini。我推薦使用Notepad++來編輯。

image

設定檔中我們要編輯的是path參數。裡面需要設定Python安裝的位置。通常Python預設安裝在「=C:\Program Files\Python27\python.exe」,而紅字的「Python27」是指你的Python版本,表示是2.7版。至於要用Python 2或Python 3是端看你的Python腳本需求,這裡並沒有特別建議要用那個版本才好。(關於Python 2跟Python 3的差異,可以看Python2和Python3備受爭議,咱們花五分鐘瞭解Python3語言特性!)

請確認你的Python是否真的安裝在這個位置。如果你沒有安裝Python,請先到Python官方網站下載安裝:

關聯程式 / Associate .py file with Python Caller

image

讓我們用同資料夾底下的example.py來設定Python腳本檔案的關聯程式。請在該檔案上按右鍵,進入「開啟檔案」中的「選擇預設程式」。

image

按右下角的「瀏覽」。

image

選擇剛剛下載的資料夾中的「Python-Caller.exe」,開啟。

image

確認Python-Caller.exe已經正確選擇了,然後按下「確定」。

image

這時候就可以看到example.py的執行結果了,是的,它就是一個「Hello, World!」。


使用 / Usage

image

如果正確設置了Python-Caller.exe,那以後只要對副檔名為「.py」的Python腳本檔案雙擊開啟,就會自動呼叫Python-Caller.exe執行Python腳本。

讓我們以循序樣式探勘:以Python的PrefixSpan實作中的Python腳本檔案prefixspan.py為例子,來看看使用Python Caller執行起來會是什麼樣子吧。該腳本還需要搭配資料檔案input.csv才能使用,請一併下載。如果你不會從GitHub下載檔案,請看如何從GitHub下載檔案這篇。

anime

以上是我用ScreenToGIF錄下來的執行過程,可以看到執行過程中變成用GUI詢問要分析的檔案跟門檻,然後就在輸入檔案旁邊得到了分析結果。這樣子執行Python腳本就很方便了呢。


Python腳本開發建議 / Hints for developing Python scripts

其實Python Caller在昨天我寫完RScript Caller的介紹之後就完成了,但後來的時間我都在研究怎麼寫一個可以獨立執行的Python腳本。最後我把心得寫在example-gui.py這個檔案中,重點如下:

在腳本中安裝套件 / Install packages  programmatically

以往我們都是在指令列以pip安裝Python的套件,但如果要讓使用者直接執行Python腳本、省下還要額外開啟命令提示字元視窗來用pip的困擾,那我們應該在Python腳本中直接呼叫pip安裝套件。

我找到比較合適的做法是來自rominf的建議,以下是在Python腳本中安裝docopt套件的做法:

# install package programmatically
import pip
def install_and_import(package):
     import importlib
     try:
         importlib.import_module(package)
     except ImportError:
         import pip
         pip.main(['install', package])
     finally:
         globals()[package] = importlib.import_module(package)

install_and_import('docopt')
from docopt import docopt

以後要安裝其他套件時,只要呼叫install_and_import()函數就可以了。

附帶一提,在R裡面安裝並匯入套件的做法還蠻常見的,做法如下:

if(!require(dplyr)){install.packages("dplyr")}

而在Node.js中似乎也有類似Python呼叫pip的做法,可以在Node.js中呼叫npm,寫法參考自hexacyanide

var npm = require('npm');
npm.load(function(err) {
   // handle errors

   // install module ffi
   npm.commands.install(['ffi'], function(er, data) {
     // log errors or data
   });

   npm.on('log', function(message) {
     // log installation progress
     console.log(message);
   });
});
使用GUI對話視窗 / GUI dialogs

Python提供了Tkinter (在Python 3叫做tkinter)的圖形化介面對話視窗功能,讓使用者可以自行指定要輸入的檔案或資料夾,以及設定的參數,非常方便。

我們在使用前必須要先載入函式庫。但是Python 2跟Python 3中此套件的名稱並不相同,我參考d-coder的做法,用以下方法來達到Python 2跟Python 3兼容的載入方式:

# Python 2-3 compatible
try:
     from Tkinter import Tk
     from tkFileDialog import askopenfilename
     from tkSimpleDialog import askinteger
except:
     from tkinter import tk
     from filedialog import askopenfilename
     from simpledialog import askinteger

然後我們就可以呼叫Tkinter的功能。以下是簡單的檔案選擇跟參數輸入的示範:

# tkinter GUI
Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
filename = askopenfilename(initialdir=os.path.dirname(os.path.realpath(sys.argv[0])),
                                     title="Please select a Python script:",
                                     filetypes=[('Python script', '.py')]) # show an "Open" dialog box and return the path to the selected file
print(filename)

intresult = askinteger("Ask a integer", "Which number you like? [1-5]",
                                  minvalue=1, maxvalue=5, initialvalue=3)
print(intresult)

不過這段範例不確定能否在Python 3裡面順利運作,有機會我再來測試吧。

image

askopenfilename()會跳出檔案選擇視窗來供使用者選擇檔案。在範例中,我還設定了一開始資料夾的路徑、對話視窗的標題跟可以選擇的檔案類型。

image

askinteger()則是請使用者輸入數字。在範例中,我也設定了對話視窗標題、內文、最小值、最大值、以及預設值。

有了這些功能,就能夠開發擁有完整GUI功能的單一Python腳本了吧。


結語 / In closing

由於這篇跟RScript Caller的內容大部分都蠻像的,所以我在後面多加了一些額外的介紹,希望未來可以用這樣的方式來開發好用的Python腳本。

Python Caller的功能就跟Python.exe本身還蠻像的,但是加入了「pause」暫停之後,就可以保留執行結果視窗以便查看。這個小功能對開發者來說格外的重要。而且還可以將多次執行的結果以獨立的命令提示資源視窗顯示,這也是很方便的地方。

好,RPython都寫完了,那下次就是回頭來改Node.js Caller吧。


這篇用Python Caller執行Python腳本的介紹就到這邊囉。你平常也都是用命令提示字元在指令端中執行Python腳本嗎?這樣子的做法跟這篇用Python Caller來呼叫,你比較喜歡那個呢?如果你有什麼建議的話,歡迎在下面留言提出指教。如果你覺得Python Caller還不錯用的話,請幫我在AddThis分享工具按讚、將這篇分享到Facebook等社群媒體吧!感謝你的耐心閱讀,讓我們下一篇見。