背景
pyinstallerでpythonファイル群をexe化したら、動いていたはずのアプリが動かない。
スタックトレースを確認したところ、ChromeDriverManager().install()でAttributeErrorが発生していた。
前提
ライブラリなど | バージョン |
---|---|
webdriver-manager | 3.8.5 |
pyinstaller | 5.9.0 |
pyinstaller-hooks-contrib | 2023.1 |
python | 3.10.7 |
再現コード
error_rep.py
from webdriver_manager.chrome import ChromeDriverManager
if __name__ == '__main__':
# オプション設定
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--disable-extensions')
options.add_argument('--proxy-server="direct://"')
options.add_argument('--proxy-bypass-list=*')
# ↓でエラー
new_driver = ChromeDriverManager().install()
service = Service(executable_path=new_driver)
return webdriver.Chrome(service=service, options=options)
ソースが記述できたのでexe化
pyinstaller error_rep.py --onefile --noconsole
すると以下のエラーが発生
Traceback (most recent call last):
File "error_rep.py", line 13, in main
File "webdriver_manager\chrome.py", line 39, in install
File "webdriver_manager\core\manager.py", line 30, in _get_driver_path
File "webdriver_manager\core\download_manager.py", line 28, in download_file
File "webdriver_manager\core\http.py", line 35, in get
File "webdriver_manager\core\utils.py", line 289, in show_download_progress
File "tqdm\std.py", line 1095, in __init__
File "tqdm\std.py", line 1344, in refresh
File "tqdm\std.py", line 1492, in display
File "tqdm\std.py", line 347, in print_status
File "tqdm\std.py", line 340, in fp_write
File "tqdm\utils.py", line 71, in __getattr__
AttributeError: 'NoneType' object has no attribute 'write'
VSコードでは問題なく動くので「何もしてないのに壊れた!」という気持ち。
原因
このページによると、ChromeDriverManager().install()を呼び出した際にコンソール上にプログレスバーが表示されるらしい。
しかしexe化する際に--noconsoleオプションを指定しているためコンソールが画面上に表示されず、「プログレスバー出力する場所がありませんよー」的な状況らしい。
解決方法
プログレスバーを出力する場所を適当に指定すればokなのでソースを以下の通り修正する
error_rep.py
from webdriver_manager.chrome import ChromeDriverManager
if __name__ == '__main__':
# オプション設定
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--disable-extensions')
options.add_argument('--proxy-server="direct://"')
options.add_argument('--proxy-bypass-list=*')
# 追加
buffer = io.StringIO()
sys.stdout = buffer
sys.stderr = buffer
new_driver = ChromeDriverManager().install()
service = Service(executable_path=new_driver)
return webdriver.Chrome(service=service, options=options)
再度pyinstallerでexe化したら行けた!