Kivy记事本PyInstaller打包exe触发RecursionError问题求助
基于Kivy的记事本PyInstaller打包递归深度溢出问题解决
我自主开发了一个基于Kivy的记事本项目,本地运行完全正常,但使用PyInstaller将其打包为.exe文件后,打开时出现maximum recursion depth exceeded错误。已尝试在.py文件和.spec文件中设置递归上限、调整Kivy日志配置等多种方案,问题仍未解决。
项目代码
from kivy.uix.screenmanager import ScreenManager, Screen from kivy.uix.filechooser import FileChooserIconView from kivy.core.window import Window import datetime from kivy.lang import Builder from kivy.app import App from kivy.config import Config import time import sys sys.setrecursionlimit(100000) # Set the show_cursor property to 0 to disable the red circle on right-click Config.set('input', 'mouse', 'mouse,multitouch_on_demand') import logging # Disable Kivy logging Config.set('kivy', 'log_level', 'error') import os os.environ['KIVY_NO_FILELOG'] = '1' # eliminate file log os.environ['KIVY_NO_CONSOLELOG'] = '1' # eliminate console logcls # Set the root logger's level to ERROR logging.getLogger().setLevel(logging.ERROR) My_notepad_kv_string=""" <MyNotepad> BoxLayout: name: 'my_notepad' orientation: 'vertical' TextInput: id: text_input background_color:'#D9F59C' background_active:'iron_man_2.jpg' BoxLayout: orientation:'horizontal' size_hint: (1, None) height:50 Button: text: "save_note" font_size : '20sp' on_press: root.texter(text_input.text) bold: True background_color :'#808000' color: '#2ADFE8' Button: text: "Clear" font_size : '20sp' bold: True background_color :'#811322' color: '#2ADFE8' on_release: text_input.text = "" """ class MyNotepad(Screen): def texter(self, text): self.your_text = text if self.your_text == "quit": MY_NOTES.get_running_app().stop() elif self.your_text != "quit": current_time = datetime.datetime.now() milliseconds = int(current_time.timestamp() * 1000) % 1000 filename = 'save_me_{}.txt'.format( current_time.strftime( '%Y-%m-%d_%H-%M-%S-{}'.format(milliseconds))) with open(filename, 'w') as saver: saver.write(self.your_text) self.ids.text_input.text = "" class MY_NOTES(App): def build(self): Builder.load_string(My_notepad_kv_string) self.icon = 'notepad_3.png' sm = ScreenManager() sm.add_widget(MyNotepad(name='my_notepad')) return sm if __name__ == '__main__': MY_NOTES().run()
打包命令
- 初始打包命令:
PyInstaller --onefile -w --icon=notepad.ico My_notepad_S+.py - 修改.spec文件添加递归上限后执行:
PyInstaller My_notepad_S+.spec
完整错误日志
Traceback (most recent call last): File "logging\__init__.py", line 1086, 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 1086, 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 1086, 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 1086, in emit AttributeError: 'NoneType' object has no attribute 'write' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "kivy\logger.py", line 248, in emit File "kivy\logger.py", line 222, in _configure File "logging\__init__.py", line 1446, in info File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1091, in emit File "logging\__init__.py", line 1004, in handleError File "kivy\logger.py", line 338, in write File "logging\__init__.py", line 1458, in warning File "logging\__init__.py", line 1589, in _log File "logging\__init__.py", line 1599, in handle File "logging\__init__.py", line 1661, in callHandlers File "logging\__init__.py", line 952, in handle File "logging\__init__.py", line 1083, in emit File "logging\__init__.py", line 927, in format File "kivy\logger.py", line 291, in format File "copy.py", line 172, in deepcopy File "copy.py", line 264, in _reconstruct RecursionError: maximum recursion depth exceeded
问题根源与解决方案
根源分析
递归溢出是日志系统循环调用导致的:使用-w参数打包会隐藏控制台,日志输出流变为None,日志输出时触发AttributeError;而日志系统在处理这个错误时又会生成新的日志,形成无限递归,最终耗尽递归深度。另外,代码中未打包的资源文件也可能触发错误日志,加剧问题。
解决步骤
1. 重构日志配置,彻底禁用无效输出
把日志相关配置移到代码最顶部,避免Kivy初始化时加载错误的日志设置:
import os # 先设置Kivy环境变量,彻底禁用日志文件和控制台输出 os.environ['KIVY_NO_FILELOG'] = '1' os.environ['KIVY_NO_CONSOLELOG'] = '1' os.environ['KIVY_LOG_MODE'] = 'null' # 直接关闭Kivy日志系统 import sys sys.setrecursionlimit(100000) from kivy.config import Config Config.set('input', 'mouse', 'mouse,multitouch_on_demand') Config.set('kivy', 'log_level', 'critical') # 仅保留致命错误日志 import logging # 重置Python标准日志,移除所有默认输出handler logging.basicConfig(level=logging.CRITICAL) for handler in logging.root.handlers[:]: logging.root.removeHandler(handler)
2. 处理未打包的资源文件
KV代码中TextInput的background_active:'iron_man_2.jpg'和App的icon='notepad_3.png',需要在打包时加入资源:
- 方法一:移除KV中的
background_active属性(如果不需要该效果) - 方法二:修改.spec文件,在
datas中添加资源路径:
datas=[('iron_man_2.jpg', '.'), ('notepad_3.png', '.')],
3. 调整打包与.spec设置
- 若仍有问题,先去掉
-w参数打包,查看真实错误:PyInstaller --onefile --icon=notepad.ico My_notepad_S+.py - 在.spec文件开头添加递归上限:
import sys sys.setrecursionlimit(100000)
4. 重新打包验证
修改完成后,重新生成.spec并执行PyInstaller My_notepad_S+.spec,打包后的.exe即可正常运行。
内容的提问来源于stack exchange,提问作者Dieharder_3
相关产品推荐
相关产品推荐

