当使用
python script.pyw
从 CLI 运行时,tkinter GUI 程序可以通过文件 IO 操作正常运行。但是,当使用 pyinstaller 将此代码转换为 Windows exe 时,在执行 df.to_csv
操作时会失败。
该程序在经过一些计算后读取 CSV。当程序尝试将刚刚执行的所有计算的数据帧写入磁盘时,会发生异常。具体错误如下:
Unhandled exception in script
Traceback (most recent call last):
File "tkinter\__init__.py", line 1948, in __call__
File "script.pyw", line 2385, in update_current_file
File "script.pyw", line 1390, in calcs
ValueError: I/O operation on closed file.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "script.pyw", line 3085, in <module>
File "tkinter\__init__.py", line 1485, in mainloop
File "tkinter\__init__.py", line 1952, in __call__
File "tkinter\__init__.py", line 1668, in _report_exception
File "tkinter\__init__.py", line 2402, in report_callback_exception
ValueError: I/O operation on closed file.
设置
使用 conda 为项目创建了新环境。创建环境时请求的包:
conda 安装了上述内容及其识别的所有依赖项。
操作
在 Anaconda 提示中,
python script.pyw
pyinstaller script.spec
script.spec的内容:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['script.pyw'],
pathex=[],
binaries=[],
datas=[('subprocess_perl_script.plx', '.'), ('icon_file.ico', '.')],
hiddenimports=[],
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)
splash = Splash('splash_image.png',
binaries=a.binaries,
datas=a.datas,
text_pos=None,
text_size=12,
minify_script=True)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
splash,
splash.binaries,
[],
name='script',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None , icon='icon_file.ico')
我可以通过回滚环境中的 matplotlib 版本号来解决这个问题。似乎后续版本中并未提供所有钩子。 Pyinstaller 使用钩子信息来收集最终可执行文件的包。
另外,顺便说一句,将环境从 conda 更改为 python venv 导致最终的 exe 大小为 40 MB,而不是 400+ MB。