跳到主要內容

如何取得利用PyInstaller所包入的資料檔案

PyInstaller可以協助我們將Python程式包裝成單一的執行檔案。同時也可以協助我們程式所需的資料檔案一併包裝起來。資料檔案一般我們都是在PyInstaller的spec檔案中加入如下的敘述:

a.datas += [('images/my.png', '/src/images/my.png', 'DATA'), ('images/other.png', '/src/images/other.png', 'DATA'), ('db/main.db', 'main.db',  'DATA')]
但是如果你在程式中寫上,像是
fd = file('db/main.db', 'rb')
或是
fd = file('main.db', 'rb')
不管是哪一個,你只有在未包裝前可以正確的開啟檔案,一旦包裝起來再執行就無法正確取得檔案了。其原因在於你的包裝好的執行檔案在執行時的時候,所有的東西會被解到一個暫時的目錄去,這個目錄你無法在寫程式的時候就確定好。所以就無法直接取得檔案。


還好網路上有人回答了這個問題。作法就是透過PyInstaller所提供的資訊來得到當時的目錄。下面這個function可以很方便的幫助你在程式中取得資料的檔案的路徑。
def rc(rel_path):
    """Return full path of resource according to rel_path."""
    if not hasattr(sys, '_MEIPASS'): 
        # for elder PyInstaller.
        rc_path = os.environ.get("_MEIPASS2", os.getcwd())
    else:
        rc_path = getattr(sys, '_MEIPASS', os.getcwd())
    return os.path.join(rc_path, rel_path)

dbfile = rc('db/main.db')
...
要注意的是,這些資料檔案應該只作為讀取的用途。寫入資料到裡面去是沒有用的。因為下一次程式執行的時候它就不見了。
Reference:
  1. Bundling data files with PyInstaller (--onefile)
張貼留言

這個網誌中的熱門文章

解決Python script無法在cp65001的console下執行的問題

你是否有這樣的經驗,明明沒問題的script,拿到某的電腦一直看到下面的訊息而無法執行。
LookupError: unknown encoding: cp65001 cp65001是什麼鬼!?其實,它就是UTF8阿!只是,Microsoft喜歡叫他cp65001(code page 65001號)。附帶一提,我們常用的Big5是cp950。想要知道你目前所使用的code page可以在Windows的console視窗執行

Portable Python

我常常需要把Python寫的script帶到其他電腦使用,因此,一個免安裝,可攜帶的Python就顯得十分重要。最近看過了幾個可攜式Python的方案,下面這個PortablePython是我覺得最合我意的方案。因為它提供了大部分會用到的Python module及工具,甚至連wxPython及PyGame也有。同時也有好用的Python編輯器PyScripter。所有開發Python所需的開發工具都一應俱全了!把它放到隨身碟中,就不用到處幫人安裝Python了。

PortablePython: http://www.portablepython.com/

有點兒怪的生蛋拌麵

前幾日在看日本的料理東西軍時,看到了一個料理是把麵煮好以後再把生蛋打上去攪和著吃。看起來滋味不俗!電視節目結束後立馬衝入廚房準備材料開始實作!

家裡沒有什麼蕎麥麵,就隨便拆了包泡麵煮熟,順便把冰箱裏面擺很久的甜不辣與貢丸拿出來一起煮熟,然後切條切片後放在麵上當配菜。