PyInstaller打包foo.exe后bar.py无法import foo的问题及方案咨询
关于PyInstaller单文件打包后外部脚本导入主模块的问题
问题现象
用PyInstaller将tkinter应用foo.py打包为单文件foo.exe,foo.py通过func_load_scripts函数调用importlib.import_module()导入指定文件夹内的.py文件(如同目录下的bar.py),运行foo.exe时出现以下现象:
- 导入标准库完全正常;
- 若
foo.py和bar.py均导入第三方模块apple,无异常; - 仅
bar.py导入apple时,触发ModuleNotFoundError; bar.py中尝试import foo时,同样触发ModuleNotFoundError。
疑问分析
bar.py无法导入foo的核心原因是:打包成单文件后,foo.py的代码被嵌入到foo.exe内部,不再以独立的.py文件形式存在于文件系统中,自然不在Python的PYTHONPATH搜索路径里。即使将PyInstaller临时解压目录sys._MEIPASS添加到sys.path也无效,因为主模块代码已被打包进可执行文件,没有单独的foo模块文件可供外部脚本导入。
需求
希望向用户暴露foo.py中的部分函数/类,支持用户在外部脚本中使用from foo import func_one这类导入方式。
现有临时方案及咨询
目前的临时方案是:创建common.py文件,将需要暴露的公共函数/类存入该文件,然后在foo.py和bar.py中均导入common模块。
咨询以下两个问题:
- 该方案是否可行?
- 是否存在其他方法,能让用户直接探测
foo.py中的其他内容,或者实现import foo的需求?
复现代码
foo.py
import importlib import os import sys sys.path.insert(1, os.getcwd()) def func_one(): print('This is foo.py') def func_load_scripts(): try: mod = importlib.import_module('bar') except ModuleNotFoundError as err: print(err) else: print(dir(mod)) finally: input('Press any key to exit...') if __name__ == '__main__': func_one() func_load_scripts()
bar.py
import foo def func_two(): print('We are in `bar.py`...') foo.func_one()
打包命令
pyinstaller --onefile foo.py
运行foo.exe且bar.py在同目录时,报错:No module named 'foo'
内容的提问来源于stack exchange,提问作者Ji Wei
相关产品推荐
相关产品推荐

