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

如何将Kivy应用打包为无控制台EXE?出现日志递归错误

Kivy应用PyInstaller无控制台打包报错问题

问题背景

使用Python 3.8和Kivy 2.2.1开发的小型应用,执行pyinstaller main.py打包后可正常运行,但会显示控制台窗口;添加--windowed、-w或--noconsole参数打包后,程序启动报错,错误信息如下:

Traceback (most recent call last):
  File "logging\__init__.py", line 1084, in emit
AttributeError: 'NoneType' object has no attribute 'write'

在处理上述异常期间,又发生了新的异常:

Traceback (most recent call last):
  File "logging\__init__.py", line 1084, in emit
AttributeError: 'NoneType' object has no attribute 'write'

重复出现多次相同错误后,最终出现:

File "logging\__init__.py", line 1002, in handleError
File "kivy\logger.py", line 390, in write
File "logging\__init__.py", line 1454, in warning
File "logging\__init__.py", line 1585, in _log
File "logging\__init__.py", line 1595, in handle
File "logging\__init__.py", line 1657, in callHandlers
File "logging\__init__.py", line 950, in handle
File "logging\__init__.py", line 1081, in emit
File "logging\__init__.py", line 925, in format
File "kivy\logger.py", line 540, in format
File "kivy\logger.py", line 424, in __init__
File "logging\__init__.py", line 318, in __init__
File "ntpath.py", line 216, in basename
File "ntpath.py", line 186, in split
File "ntpath.py", line 35, in _get_bothseps
RecursionError: maximum recursion depth exceeded while calling a Python object

错误原因

Kivy默认日志系统依赖控制台的标准输出/错误流(sys.stdout/sys.stderr)。当使用--windowed等无控制台参数打包时,PyInstaller会将标准流设置为None,日志模块尝试向None对象写入内容触发AttributeError;而Kivy的日志处理逻辑在捕获该错误时,又会尝试输出新的日志,最终引发无限递归,触发RecursionError。

解决方法

方法1:修改Kivy日志配置,改用文件日志

在应用入口文件main.py最开头添加日志配置,移除控制台日志处理器,改用文件记录日志:

import logging
import sys
from kivy.logger import Logger

# 移除所有控制台日志处理器
for handler in Logger.handlers[:]:
    if isinstance(handler, logging.StreamHandler):
        Logger.removeHandler(handler)

# 添加文件日志处理器,日志写入app.log
file_handler = logging.FileHandler('app.log', encoding='utf-8')
log_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')
file_handler.setFormatter(log_formatter)
Logger.addHandler(file_handler)
Logger.setLevel(logging.INFO)

# 可选:重定向sys.stdout和sys.stderr到文件,避免其他依赖标准流的代码报错
sys.stdout = open('stdout.log', 'w', encoding='utf-8')
sys.stderr = open('stderr.log', 'w', encoding='utf-8')

方法2:补充PyInstaller缺失的Kivy依赖

打包时指定Kivy的依赖模块,确保PyInstaller正确识别所有必要组件:

pyinstaller --windowed --hidden-import=kivy.deps.sdl2 --hidden-import=kivy.deps.glew --hidden-import=kivy.deps.angle main.py

方法3:修改PyInstaller spec文件,重定向标准流

  1. 先生成spec文件:
    pyinstaller --windowed main.py
    
  2. 打开生成的main.spec文件,在EXE配置块中添加stdout和stderr参数,将标准流重定向到日志文件:
    exe = EXE(pyz,
              a.scripts,
              a.binaries,
              a.zipfiles,
              a.datas,
              [],
              name='main',
              debug=False,
              bootloader_ignore_signals=False,
              strip=False,
              upx=True,
              upx_exclude=[],
              runtime_tmpdir=None,
              console=False,
              stdout='app_stdout.log',
              stderr='app_stderr.log'
              )
    
  3. 使用spec文件重新打包:
    pyinstaller main.spec
    

内容的提问来源于stack exchange,提问作者Shehara Winod

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:52:48