PyInstaller编译exe时遭遇FileNotFoundError问题求助
我尝试编译一个exe文件,但一直遇到FileNotFoundError错误,报错信息如下:
Traceback (most recent call last): File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\runpy.py", line 197, in _run_module_as_main return _run_code(code, main_globals, None, File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\runpy.py", line 87, in _run_code exec(code, run_globals) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\Scripts\pyinstaller.exe\__main__.py", line 7, in <module> sys.exit(_console_script_run()) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\__main__.py", line 228, in _console_script_run run() File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\__main__.py", line 212, in run run_build(pyi_config, spec_file, **vars(args)) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\__main__.py", line 69, in run_build PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\building\build_main.py", line 1139, in main build(specfile, distpath, workpath, clean_build) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\building\build_main.py", line 1079, in build exec(code, spec_namespace) File "C:\Users\source\repos\PowerProjects\Solutions\HQ Daily Hedge Report\DHR_SwapTradingExposure\DHR_SwapTradingExposure.spec", line 35, in <module> coll = COLLECT( File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\building\api.py", line 1092, in __init__ self.__postinit__() File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\building\datastruct.py", line 184, in __postinit__ self.assemble() File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\PyInstaller\building\api.py", line 1164, in assemble shutil.copyfile(src_name, dest_path) File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\shutil.py", line 266, in copyfile with open(dst, 'wb') as fdst: FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\source\\repos\\PowerProjects\\Solutions\\HQ Daily Hedge Report\\DHR_SwapTradingExposure\\dist\\DHR_SwapTradingExposure\\_internal\\jedi\\third_party\\typeshed\\third_party\\2and3\\requests\\packages\\urllib3\\packages\\ssl_match_hostname\\_implementation.pyi'
我的目录结构里有两个项目文件夹:
C:\Users\source\repos\PowerProjects\Solutions\HQ Daily Hedge Report\DHR_SwapTradingExposureC:\Users\source\repos\PowerProjects\Solutions\HQ Daily Hedge Report\DHR_ConsolidateMarks
用pyinstaller --onedir --add-data "config1.json;." DHR_ConsolidateMarks.py编译第二个项目时完全正常,但用pyinstaller --onedir --add-data "config.json;." DHR_SwapTradingExposure.py编译第一个项目就会出现上面的文件找不到错误,我完全搞不懂为什么会这样,有没有人能帮我解决这个问题?
可能的解决思路
看起来这个问题是PyInstaller在收集依赖文件时,尝试复制一个不存在的_implementation.pyi文件导致的,大概率和jedi库的依赖收集有关。这里有几个你可以尝试的方案:
清理PyInstaller缓存后重新编译
有时候缓存的旧文件会导致奇怪的问题,先删除项目里的build、dist文件夹和生成的.spec文件,然后重新运行编译命令:rmdir /s /q build dist del DHR_SwapTradingExposure.spec pyinstaller --onedir --add-data "config.json;." DHR_SwapTradingExposure.py排除jedi相关的不必要依赖
如果你的项目并没有用到jedi库(它通常是代码补全工具的依赖),可以在编译时主动排除它:pyinstaller --onedir --add-data "config.json;." --exclude-module jedi DHR_SwapTradingExposure.py如果确实需要用到
jedi,那可以尝试升级jedi和PyInstaller到最新版本,可能是旧版本的兼容性问题:pip install --upgrade jedi pyinstaller手动创建缺失的目录或文件
报错里提到的路径是dist\DHR_SwapTradingExposure\_internal\jedi\third_party\typeshed\third_party\2and3\requests\packages\urllib3\packages\ssl_match_hostname,你可以手动创建这个目录结构,甚至可以从jedi的安装目录里找到对应的_implementation.pyi文件复制过去,然后再重新编译。
你可以在Python的site-packages目录里找jedi的位置,比如C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\site-packages\jedi,然后找到对应的文件路径复制过去。修改.spec文件跳过该文件
生成.spec文件后,打开它找到COLLECT部分,尝试添加排除规则,或者修改文件收集的逻辑,跳过这个不存在的文件。比如在a = Analysis(...)部分的excludes列表里加上对应的路径,或者在COLLECT里过滤掉这个文件。
备注:内容来源于stack exchange,提问作者iBeMeltin

