利用pyinstaller將python腳本打包發佈

  以前寫了一個小工具,將excel配置錶轉換爲json、xml、lua等配置文件。最近在學習egret,正好須要轉換配置文件,恰好就用上了。然而當我想把工具拷到工做目錄時,就發愁了。以前我爲了方便擴展,把程序拆分得太細:html

xzc@xzc-HP-ProBook-4446s:~/Documents/code/github/py_exceltools$ ls -lh
總用量 80K
drwxrwxr-x 2 xzc xzc 4.0K  7月 27 23:03 bin
drwxrwxr-x 2 xzc xzc 4.0K  7月 27 23:03 client
-rw-rw-r-- 1 xzc xzc 7.7K  7月 27 23:03 decoder.py
-rw-rw-r-- 1 xzc xzc  893  7月 27 23:03 error.py
-rw-rw-r-- 1 xzc xzc  16K  7月 27 23:03 example.xlsx
-rw-rw-r-- 1 xzc xzc  131  7月 27 23:03 lancher.bat
-rw-rw-r-- 1 xzc xzc  127  7月 27 23:03 lancher.sh
-rw-rw-r-- 1 xzc xzc 3.9K  7月 27 23:03 loader.py
-rw-rw-r-- 1 xzc xzc  705  7月 27 23:03 loader.spec
-rw-rw-r-- 1 xzc xzc 2.4K  7月 27 23:03 README.md
drwxrwxr-x 2 xzc xzc 4.0K  7月 27 23:03 server
-rw-rw-r-- 1 xzc xzc 4.0K  7月 27 23:03 writer_json.py
-rw-rw-r-- 1 xzc xzc 7.2K  7月 27 23:03 writer_lua.py
-rw-rw-r-- 1 xzc xzc 5.6K  7月 27 23:03 writer_xml.py

如此多的文件,放到工做目錄不太好組織,也容易與項目的源代碼混在一塊兒。畢竟我用的vs code分不清哪些纔是工程內文件。況且之後還要給策劃用,還得裝python和openpyxl庫,部署比較麻煩。因而想嘗試一下把python腳本打包爲一個exe文件。python

  google了一下,經常使用的工具不外乎pyinstaller和py2exe。二者的功能都差很少,可是發現pyinstaller有一個參數 --onefile,即腳本都打包成單個可運行文件,這不正是我要的麼。因而下載安裝來嘗試一下:linux

py_exceltools$pip install pyinstaller
py_exceltools$pyinstaller -F loader.py

...
tuple index out of range

安裝過程很順利,可是打包時卻報了個錯("tuple index out of range")。google一下"pyinstaller tuple index out of range",在github中發現是pyinstaller3.2.1不兼容python3.6.1。可是看看issue的回覆,在dev版本是修復了。因而想試一下開發版本,不過看了一眼README,發現OS X、Linux、Win三個平臺的CI都是failing:git

想一想仍是算了吧,省得折騰半天又不能用。直接把本機的python從3.6.1降爲3.5,再重新安裝pyinstaller,運行"pyinstaller -F loader.py"打包,一切順利,在dist目錄下生成了一個loader.exe。試運行下loader.exe,結果倒是這樣的:github

Traceback (most recent call last):
File "loader.py", line 96, in <module>
options.timeout,options.suffix,options.srv_writer,options.clt_writer )
File "loader.py", line 25, in __init__
self.srv_writer = importlib.import_module( "writer_" + srv_writer )
File "importlib\__init__.py", line 126, in import_module
File "<frozen importlib._bootstrap>", line 986, in _gcd_import
File "<frozen importlib._bootstrap>", line 969, in _find_and_load
File "<frozen importlib._bootstrap>", line 956, in _find_and_load_unlocked
ImportError: No module named 'writer_lua'
Failed to execute script loader
請按任意鍵繼續. . .

缺失了模塊writer_lua,這是我本身寫的一個轉換爲Lua配置的模塊。pyinstaller原本有分析腳本依賴的模塊的,可是我這個程序是根據運行時傳入的參數動態加載模塊的,由於我並不能預先知道用戶要把excel轉換爲何類型的文件。所有加載全部模塊,是一個解決方案,但不太合適,由於我原本的寫法是:規定了模塊的接口,新增模塊時,不須要修改我原有的代碼,會自動加載新模塊。再次搜索了一下,竟然沒有找到相同的案例。閱讀了下pyinstaller的手冊(https://pythonhosted.org/PyInstaller/spec-files.html),發現能夠用spec配置文件來打包各類數據的,好比程序的icon,甚至自定義的一些二進制文件。在http://pythonhosted.org/PyInstaller/when-things-go-wrong.html#listing-hidden-importshttp://pythonhosted.org/PyInstaller/hooks.html#understanding-pyinstaller-hooks中提到可使用hiddenimports選項來導入隱藏的模塊。json

  查看了下pyinstaller打包的過程,運行"pyinstaller -F loader.py"時確實在當前目錄下生成了一個loader.spec文件:bootstrap

# -*- mode: python -*-

block_cipher = None


a = Analysis(['loader.py'],
             pathex=['E:\\linux_share\\github\\py_exceltools'],
             binaries=[],
             datas=[],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='loader',
          debug=False,
          strip=False,
          upx=True,
          console=True )

在hiddenimports中加入本身動態加載的模塊,變成hiddenimports=['writer_lua','writer_xml','writer_json'],從新打包。注意,從新打包時不要再運行"pyinstaller -F loader.py"了,由於這個指令會從新生成spec文件,把你修改的覆蓋了。直接用"pyinstaller loader.spec"來打包。工具

  加入動態加載的模塊後,整個exe有7M多,運行正常。可是在64bit系統打包出來的程序,是64bit的,不能在32bit下運行。整個工具放在github上:https://github.com/changnet/py_exceltools學習

相關文章
相關標籤/搜索