在kivy中超过了最大递归深度,但仅在打包时才这样做,而在python中开发应用程序时则没有

时间:2019-02-01 01:53:15

标签: python kivy pyinstaller

我正在尝试打包一个需要多次导入的应用,其中包括matplotlib.pyplot

kivy应用程序(已简化,但仍在运行)是:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
import matplotlib.pyplot


Builder.load_string("""
<MyWidget>:
    id: my_widget
    FileChooserIconView:
        id: filechooser
        on_selection: my_widget.selected(filechooser.selection)
    Image:
        id: image
        source: ""
""")


class MyWidget(BoxLayout):

    def selected(self,filename):
        self.ids.image.source = filename[0]


class MyApp(App):
    def build(self):
        return MyWidget()


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

该应用程序在使用spyder的python中完美运行。

但是,当我尝试将其打包为独立的kivy应用程序时,它给了我错误,超过了最大递归深度。

我很惊讶,不知道是什么原因,因为:

1。应用程序中没有递归函数。

2。在开发和测试python spyder时可以完美地工作,唯一的问题是在包装过程中。

3。我尝试了多个选项,包括注释了几个部分,最令人惊讶的是,当我注释了导入matplotlib.pyplot应用程序包时,它很好。但是,我需要此应用程序使用matplotlib.pyplot,因此将其取出不是一种选择。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
#import matplotlib.pyplot


Builder.load_string("""
<MyWidget>:
    id: my_widget
    FileChooserIconView:
        id: filechooser
        on_selection: my_widget.selected(filechooser.selection)
    Image:
        id: image
        source: ""
""")


class MyWidget(BoxLayout):

    def selected(self,filename):
        self.ids.image.source = filename[0]


class MyApp(App):
    def build(self):
        return MyWidget()


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

上面的代码可以很好地工作和打包。

可以导入到kivy应用程序的文件大小是否有一定限制?我已经尝试使用sys.setrecursionlimit(high number)增加递归限制,但这不是解决此问题的方法。 我真的迷路了。任何见解表示赞赏。

谢谢

编辑2/4/2019: 有人提出这个问题:pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object是重复的,可以回答这个问题。尽管这绝对是一个相关的问题,并且很有帮助,但我的错误发生在创建kivy包的第一阶段: python -m PyInstaller --name touchtracer examples-path \ demo \ touchtracer \ main.py

2 个答案:

答案 0 :(得分:1)

当我们进行递归时,存在堆栈溢出的风险,并且在后台运行的Cpython本身不会利用它来优化尾部递归,因此,如果您做得太深,您将朝着堆栈溢出靠近。通常,不同的Cpython / python风格具有不同的递归许可深度,您在本地运行的python版本具有更宽松的深度限制(通常是因为假定开发人员具有足够好的计算机可以进行此操作)。但是,当您使用工具打包应用程序时,它们通常会将sys.setrecursionlimit改写为更保守的值,因为它们会尝试确保不会在硬件较低的系统上引起堆栈溢出。

遗憾的是,此问题没有灵丹妙药,您可以尝试调查您的特定经理并更改限制(不推荐),也可以尝试将递归块转换为迭代块。

答案 1 :(得分:1)

非常感谢所有尝试提供帮助的人。 我找到了答案,希望它对尝试创建kivy软件包的其他人有所帮助,并且在导入python模块时出现问题。

一旦您准备好打包main.py脚本:

1。从以下说明开始

https://kivy.org/doc/stable/guide/packaging-windows.html

并执行第一步:

python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py

这将给您带来maximum recursion depth exceeded的错误或最初给您的任何错误。别担心。此步骤的目的是创建一个初始spec文件。

2。打开spec文件,并在

处添加kivy指令为您提供的所有其他功能
https://kivy.org/doc/stable/guide/packaging-windows.html

即:

from kivy.deps import sdl2, glew
Tree('examples-path\\demo\\touchtracer\\'),
*[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],

3。除此之外,在spec文件的开头添加以下内容:

import sys
sys.setrecursionlimit(5000) # (or some big number)

4。还要在您可能需要的隐藏导入中添加任何导入。

hiddenimports=[] # change to (example importing pandas and matplotlib) hiddenimports=['pandas', 'matplotlib']

5。只需按照

的最后一步
https://kivy.org/doc/stable/guide/packaging-windows.html

即:

python -m PyInstaller touchtracer.spec

并构建您的应用