能否在PyInstaller的.spec文件中以hidden_import包含exe并通过subprocess.Popen运行?
问题
是否可以在PyInstaller的.spec文件中,将exe文件以hidden_import的方式包含进去,然后在主Python脚本中使用subprocess.Popen命令来运行它?
我遇到如下错误:
Traceback (most recent call last): File "running_example.py", line 40, in <module> s = shout.Shout() File "shout.py", line 66, in __init__ self.p1 = Popen([resource_path0("msys_shout.exe")], stdin=PIPE, stdout=PIPE,shell=False, universal_newlines=True, bufsize=1, close_fds=ON_POSIX) File "subprocess.py", line 969, in __init__ File "subprocess.py", line 1438, in _execute_child FileNotFoundError: [WinError 2] The system cannot find the file specified
resource_path0函数定义如下:
def resource_path0(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr( sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)
我的.spec文件内容如下:
# -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis( ['running_example.py'], pathex=[], binaries=[], datas=[], hiddenimports=["msys_shout.*","shout.*","*.mp3"], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, ) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE( pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='running_example', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, )
解答
不行,hidden_import仅用于告知PyInstaller打包未被自动检测到的Python模块,exe属于二进制可执行文件,无法通过hidden_import包含,这正是你出现文件找不到错误的原因。
要打包exe这类二进制文件,需修改.spec文件的binaries参数,具体步骤如下:
- 假设
msys_shout.exe与主脚本在同一目录,将binaries修改为:
元组格式为binaries=[('msys_shout.exe', '.')],(源文件路径, 打包后存放的相对路径),.表示与主exe放在同一目录。 - 若有mp3这类资源文件,需放入
datas参数而非hidden_import:datas=[('*.mp3', '.')], - 清理
hidden_imports中不属于Python模块的内容,仅保留需要的模块,例如:hiddenimports=["shout"],
修改后的.spec文件的Analysis部分如下:
a = Analysis( ['running_example.py'], pathex=[], binaries=[('msys_shout.exe', '.')], datas=[('*.mp3', '.')], hiddenimports=["shout"], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False, )
修改完成后,重新执行打包命令:
pyinstaller running_example.spec
这样msys_shout.exe会被打包到主exe的同一目录(或你指定的路径),resource_path0函数能正确定位到它,subprocess.Popen即可正常运行。
内容的提问来源于stack exchange,提问作者Chris P
相关产品推荐
相关产品推荐

