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

Python Kivy应用打包EXE后出现RecursionError问题求助

Kivy应用打包为EXE后运行报错:AttributeError与RecursionError

错误信息

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

During handling of the above exception, another exception occurred:

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

...

RecursionError: maximum recursion depth exceeded

程序代码

main.py

import random
import sys
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.config import Config

Config.set('graphics', 'resizable', '0')

# Designate Our .kv design file
Builder.load_file('main.kv')

class MyLayout(Widget):

    def release(self):
        self.ids.my_button.background_color = 5 / 255, 225 / 255, 120 / 255, 1
        self.ids.my_button.color = 1, 1, 1, 1

    def press(self):
        # Create variables for our widget
        # Update the label
        deck = list(range(1, 43))
        random.shuffle(deck)
        # Create list of 6 values, and assign each with a number between 1 and 42
        random_numbers = [0, 1, 2, 3, 4, 5]
        for i in range(0, 6):
            random_numbers[i] = deck.pop()

        # Sort the array from lowest to highest
        random_numbers.sort()
        self.ids.my_button.background_color = 50 / 255, 225 / 255, 120 / 255, 1
        self.ids.my_button.color = 180 / 255, 180 / 255, 180 / 255, 1

        self.ids.name_label.text = f'{random_numbers[0]}    ' \
                                   f'{random_numbers[1]}    ' \
                                   f'{random_numbers[2]}    ' \
                                   f'{random_numbers[3]}    ' \
                                   f'{random_numbers[4]}    ' \
                                   f'{random_numbers[5]}'
class AwesomeApp(App):
    def build(self):
        return MyLayout()

sys.setrecursionlimit(2000)

if __name__ == '__main__':
    AwesomeApp().run()

main.kv

<MyLayout>
   BoxLayout:
      orientation: "vertical"
      size: root.width, root.height

      Label:
          font_name: "files/cambriab.ttf"
          id: name_label
          text: "If you had 530M dinars, what would you do with it?"
          font_size: 32


      Button:
          id: my_button
          size_hint: .4, .2
          font_size: 32
          font_name: "files/cambriaz.ttf"
          text: "Make me rich!"
          pos_hint: {'center_x': 0.5}
          background_color: 5/255,225/255,120/255,1
          on_press: root.press()
          on_press: hassanGIF.anim_delay = 1/50
          on_press: hassanGIF._coreimage.anim_reset(True)
          on_release: root.release()

          Image:
              id: hassanGIF
              source: 'files/sequence.zip'
              anim_delay : -1
              anim_loop: 1
              center_x: self.parent.center_x
              center_y: self.parent.center_y+400
              size: root.width-400, root.height-400

已尝试操作

  • 用多种打包工具打包,均无效
  • 设置sys.setrecursionlimit(2000),未解决递归错误

解决方案

1. 修复日志输出的NoneType问题

打包后Kivy默认日志输出流会变为None,需手动配置日志处理器:
在main.py开头添加以下代码:

import logging
from logging.handlers import RotatingFileHandler

# 重置日志配置,避免输出流为空
logger = logging.getLogger('kivy')
logger.handlers.clear()
handler = RotatingFileHandler('app.log', maxBytes=1024*1024, backupCount=5)
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logger.addHandler(handler)
logger.setLevel(logging.INFO)

2. 修复递归错误根源

递归错误并非单纯提升上限就能解决,问题出在私有API调用上:

  • 移除main.kv中on_press: hassanGIF._coreimage.anim_reset(True)这一行
  • 替换为Kivy官方支持的动画重置方法,修改后的on_press事件如下:
on_press: root.press()
on_press: hassanGIF.reload()
on_press: hassanGIF.anim_delay = 1/50

3. 规范PyInstaller打包配置

使用PyInstaller打包时,必须正确包含资源和依赖:

  1. 创建app.spec文件:
# -*- mode: python ; coding: utf-8 -*-
from kivy_deps import sdl2, glew

block_cipher = None

a = Analysis(
    ['main.py'],
    datas=[('files/*', 'files')],  # 打包files目录下的所有资源
    hiddenimports=['kivy.core.window.window_sdl2'],
    cipher=block_cipher,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.zipfiles,
    a.datas,
    *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
    name='AwesomeApp',
    console=False,  # 不需要控制台窗口可设为False,调试时设为True
    upx=True,
)
  1. 执行打包命令:
pyinstaller app.spec

4. 其他注意事项

  • 确保files目录下的字体、GIF压缩包路径正确,打包时已被包含
  • 移除代码中的sys.setrecursionlimit(2000),递归错误解决后无需修改默认上限

内容的提问来源于stack exchange,提问作者Ballen Abdullah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:05:37