PyInstaller打包后无法通过psutil.Popen调用另一个.py文件的技术问题
PyInstaller打包后无法调用外部Python脚本的解决方案
这个问题我碰到过好多次啦,PyInstaller打包后的exe和原Python脚本的运行环境差得挺多,咱们一步步拆解问题根源,再给你靠谱的解决办法:
为什么会出问题?
- 找不到Python解释器:打包后的exe是独立运行的,系统里可能没装Python,就算装了,
python命令在打包后的临时运行环境里也不一定能被找到(比如你用了虚拟环境,打包后就脱离了这个环境)。 - 脚本路径不对:PyInstaller默认不会自动把file2.py打包进去,而且exe运行时的当前工作目录可能不是你原脚本所在的文件夹,导致找不到file2.py。
- shell=True的坑:依赖系统shell环境调用命令,有时候会触发权限或者路径解析的问题,尤其是在Windows系统上。
最推荐的解决办法(把file2.py打包进exe)
这个方案不需要用户机器装Python,兼容性最好:
步骤1:打包时把file2.py包含进去
用PyInstaller命令打包file1.py的时候,加上--add-data参数把file2.py作为数据文件打包进去。Windows系统用分号分隔路径,Linux/macOS用冒号:
# Windows pyinstaller --onefile --add-data "file2.py;." file1.py # Linux/macOS pyinstaller --onefile --add-data "file2.py:." file1.py
步骤2:修改file1.py里的调用代码
要先获取打包后的exe的运行路径,再用自带的Python解释器运行file2.py,代码改成这样:
from psutil import Popen import sys import os def get_resource_path(relative_path): # 兼容脚本运行和exe运行的路径获取 try: # 打包后,PyInstaller会把文件放在这个临时目录里 base_path = sys._MEIPASS except Exception: # 未打包时,用当前脚本的目录 base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) # 获取file2.py的正确路径 file2_full_path = get_resource_path("file2.py") # 用打包后的Python解释器运行file2.py,关掉shell=True更安全 Popen([sys.executable, file2_full_path], shell=False)
备选方案:把file2.py也打包成独立exe
如果你希望file2.py作为单独的exe运行:
- 先把file2.py打包成exe:
pyinstaller --onefile file2.py
- 把file2.exe和file1.exe放在同一个目录,然后修改file1.py里的调用:
from psutil import Popen import os # 获取file2.exe的路径 file2_exe_path = os.path.join(os.path.dirname(__file__), "file2.exe") Popen([file2_exe_path], shell=False)
记得打包file1.exe时,也要用--add-data "file2.exe;."把file2.exe包含进去。
不推荐的方案(依赖系统Python)
如果你的用户机器肯定装了Python,也可以指定Python的完整路径来调用,但兼容性很差,比如:
Popen(["C:/Python39/python.exe", "file2.py"], shell=False)
这种方式不建议,因为不同用户的Python安装路径可能不一样。
排查小技巧
打包后先在命令行运行file1.exe,这样能看到实时的报错信息,方便快速定位问题(比如找不到file2.py或者解释器的错误)。
内容的提问来源于stack exchange,提问作者Jin jin
相关产品推荐
相关产品推荐

