前言
昨天決定分享一下最近寫的exhentai爬蟲程式,參考了這篇文章,看了下里面幾個常見打包軟體的簡介表格(可惜沒nuitka)
因為是給小白使用者使用,做成單個檔案形式,只能在Pyinstaller和py2exe之間選擇
去各自官網看了下,發現py2exe很久沒更新了,對python3新版本的支援也不是太好,就決定用Pyinstaller來封裝/打包
這裡略過Pyinstaller的安裝和使用,重點說明症狀,分析過程,解決辦法和教訓
症狀
-
打包成功
-
執行程式時出現如下報錯
C:UsersxoxoPycharmProjectsHentai_Spider>main
Traceback (most recent call last):
File "main.py", line 6, in <module>
from config import args
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1129, in _exec
File "C:Python34libsite-packagesPyInstallerloaderpyimod03_importers.py",
line 631, in exec_module
exec(bytecode, module.__dict__)
File "config.py", line 11, in <module>
parser.add_argument(`-sd`, `--savedir`, default=config[`ARGS`][`SAVEDIR`])
File "configparser.py", line 936, in __getitem__
KeyError: `ARGS`
[7836] Failed to execute script main
C:UsersxoxoPycharmProjectsHentai_Spider>
分析過程
0 . StackOverflow搜了下發現沒啥經驗可供參考……
1 . main.py程式是完全可以跑通的,從未出現過這個報錯,所以確定問題出在封裝過程中
2 . 報錯資訊上看,是(封裝後的程式)執行config.py時出了問題
3 . 通過控制變數排除法(過程比較繁瑣,不一一列舉),確定是在讀取config.ini時出的錯,把賦值config_path這裡改成確定的路徑即可正常執行
程式碼如下:
config = configparser.ConfigParser()
config_path = os.path.join(os.path.dirname(__file__), CONFIG_FILE)
config.read(config_path)
順便解釋一下,我的設計意圖是讓config.py去讀取其所在目錄下的配置檔案,main.py和config.py在同一目錄
4 . 由於CONFIG_FILE是常量(檔名),那最終就懷疑到os.path.dirname(__file__)部分
5 . 在賦值config_path =這句後加上print(os.path.dirname(__file__),看看封裝後這裡的file會到哪個目錄,發現變成了C:UsersxoxoAppDataLocalTemp\_MEI92882
C:UsersxoxoPycharmProjectsHentai_Spider>main
C:UsersxoxoAppDataLocalTemp\_MEI92882
Traceback (most recent call last):
File "main.py", line 6, in <module>
from config import args
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1129, in _exec
File "C:Python34libsite-packagesPyInstallerloaderpyimod03_importers.py",
line 631, in exec_module
exec(bytecode, module.__dict__)
File "config.py", line 12, in <module>
parser.add_argument(`-sd`, `--savedir`, default=config[`ARGS`][`SAVEDIR`])
File "configparser.py", line 936, in __getitem__
KeyError: `ARGS`
[9296] Failed to execute script main
C:UsersxoxoPycharmProjectsHentai_Spider>
6 . 可以看到config.py雖然封裝前和main.py在一個資料夾下,但被封裝後,執行時就處於臨時資料夾,這時候取其自身所在目錄的動作就有問題
解決方案
main.py來抓目錄資訊,再傳給config.py(中函式)
教訓
-
封裝程式沒有聰明到能理解設計意圖,所以寫程式碼的得更聰明點
-
如果某專案可能會被封裝,讓被封裝的那個程式來抓取目錄資訊並傳遞