You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 10:40:37