以前寫了一個小工具,將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-imports和http://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學習