PyInstaller打包生成的.exe文件无法运行问题求助
PyInstaller打包Eel项目生成的.exe运行报错:AttributeError: 'NoneType' object has no attribute 'write'
报错信息
Traceback (most recent call last): File "main.py", line 5, in <module> File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module File "eel\__init__.py", line 8, in <module> File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "PyInstaller\loader\pyimod02_importers.py", line 499, in exec_module File "bottle.py", line 73, in <module> AttributeError: 'NoneType' object has no attribute 'write'
使用的打包命令
pyinstaller --noconfirm --onedir --windowed --icon icon.ico --name "Useful Tools for Windows" --uac-admin --add-data "web;web/" main.py
项目源代码
# Imports system commands import os # Imports eel, a Electron like GUI for Python. import eel eel.init("web") # Fixes Chrome not installed. eel.browsers.set_path( "chrome", "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" ) @eel.expose def openHosts(): os.system( "attrib -r %WINDIR%\system32\drivers\etc\hosts && start notepad.exe %windir%\system32\drivers\etc\hosts" ) @eel.expose def openOfficeAddins(): os.system("explorer.exe %AppData%\Microsoft\AddIns") @eel.expose def openCurrentUserStartMenu(): os.system("explorer.exe %AppData%\Microsoft\Windows\Start Menu") @eel.expose def openAllUserStartMenu(): os.system("explorer.exe C:\ProgramData\Microsoft\Windows\Start Menu") @eel.expose def openSentTo(): os.system("explorer.exe %Appdata%\Microsoft\Windows\SendTo") @eel.expose def openCurrentUserStartup(): os.system("explorer.exe %AppData%\Microsoft\Windows\Start Menu\Programs\Startup") @eel.expose def openAllUsersStartup(): os.system( "explorer.exe C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp" ) @eel.expose def openWordStartup(): os.system("explorer.exe %AppData%\Microsoft\Word\STARTUP") @eel.expose def openPSReadLineHistory(): os.system( "notepad %AppData%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" ) @eel.expose def installYouTubeDownloader(): os.system("winget install MoheshwarAmarnathBiswas.YouTubeVideoDownloader") @eel.expose def installPowerToys(): os.system("winget install Microsoft.PowerToys") @eel.expose def installSysInternals(): os.system("winget install --id 9P7KNL5RWT25") @eel.expose def openAccountPictures(): os.system("explorer shell:AccountPictures") @eel.expose def openFolderOptions(): os.system("explorer shell:::{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}") @eel.expose def openInternetOptions(): os.system("explorer shell:::{A3DD4F92-658A-410F-84FD-6FBBBEF2FFFE}") @eel.expose def openSoundOptions(): os.system("explorer shell:::{F2DDFC82-8F12-4CDD-B7DC-D4FE1425AA4D}") @eel.expose def openPowerOptions(): os.system("explorer shell:::{025A5937-A6BE-4686-A844-36FE4BEC8B6D}") @eel.expose def openOptionalFeatures(): os.system("start %WINDIR%\System32\OptionalFeatures.exe") @eel.expose def openControlPanel(): os.system("start control.exe") @eel.expose def wsreset(): os.system("start wsreset.exe") @eel.expose def wureset(): os.system("net stop bits") os.system("net stop wuauserv") os.system("net stop CryptSvc") os.system("net stop msiserver") os.system("del %windir%\SoftwareDistribution") os.system("del %windir%\system32\catroot2") os.system("net start bits") os.system("net start wuauserv") os.system("net start CryptSvc") os.system("net start msiserver") @eel.expose def openGodMode(): os.system("explorer.exe shell:::{ed7ba470-8e54-465e-825c-99712043e01c}") eel.start("index.html")
项目依赖
altgraph==0.17.3 black==22.12.0 bottle==0.12.23 bottle-websocket==0.2.9 cffi==1.15.1 click==8.1.3 colorama==0.4.6 Eel==0.15.1 future==0.18.3 gevent==22.10.2 gevent-websocket==0.10.1 greenlet==2.0.1 mypy-extensions==0.4.3 pathspec==0.10.3 pefile==2022.5.30 platformdirs==2.6.2 pycparser==2.21 pyinstaller==5.7.0 pyinstaller-hooks-contrib==2022.15 pyparsing==3.0.9 pywin32-ctypes==0.2.0 tomli==2.0.1 whichcraft==0.6.1 zope.event==4.6 zope.interface==5.5.2
环境信息
- 使用Microsoft Store版本的Python
- 已启用venv虚拟环境
已尝试的解决方法
- 安装wheel并重新安装依赖
- 将
C:\Windows\System32\downlevel添加到系统路径 - 重新创建venv
解决方案
原因分析
报错源于使用--windowed参数打包后,程序没有控制台窗口,导致sys.stdout和sys.stderr被设置为None。而bottle库在初始化时会尝试向这些流写入日志信息,从而触发AttributeError。
方法1:重定向标准输出/错误流到空设备
在项目代码开头(导入eel之前)添加以下代码,将标准输出和错误重定向到空设备,避免bottle写入None对象:
import sys import os # 处理无控制台时的stdout/stderr为None的情况 if sys.stdout is None: sys.stdout = open(os.devnull, 'w') if sys.stderr is None: sys.stderr = open(os.devnull, 'w')
方法2:修改打包命令
- 如果可以接受显示控制台窗口,去掉
--windowed参数,改用默认的--console模式,这样程序运行时会弹出控制台,stdout/stderr正常可用。 - 如果必须保持无窗口,可使用自定义PyInstaller钩子来处理bottle的输出。创建一个
hook-bottle.py文件,内容如下:
然后打包时添加import sys import os def pre_safe_import_module(api): if sys.stdout is None: sys.stdout = open(os.devnull, 'w') if sys.stderr is None: sys.stderr = open(os.devnull, 'w')--additional-hooks-dir=.参数,指定钩子所在目录。
方法3:升级bottle版本
较新的bottle版本可能已经修复了无控制台环境下的输出问题,尝试升级bottle到最新稳定版:
pip install --upgrade bottle
内容的提问来源于stack exchange,提问作者Moheshwar Amarnath Biswas
相关产品推荐
相关产品推荐

