1

I am trying to pack an app that requires several imports, among those matplotlib.pyplot

The kivy app (simplified, but still working) is:

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()

This app works perfectly in python using spyder.

However, when I try to pack it as an independent kivy app it gives me error maximum recursion depth exceeded.

I am surprised and I do not know what the problem is because:

1.There are no recursive functions in the app.

2.Works perfectly in python spyder while developing it and testing it, the only problem is during packaging.

3.I have tried multiple options, including commenting out several portions and, most surprising, when I comment out the import matplotlib.pyplot the app packages well. However I need matplotlib.pyplot for this app so taking it out is not an option.

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()

The above code works and packages well.

Is it that there is some limit of the size of the files one can import to a kivy app? I have already tried to increase the recursion limit with sys.setrecursionlimit(high numbers) but it is not a solution to this problem. I am really lost. Any insight appreciated.

Thank you

Edit 2/4/2019: It has been suggested that the question: pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object is a duplicate and answers this question. Although this is definitively a related question and is helpful, my error occurs in the first stage of the creation of the kivy package: python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py

6
  • What are you using to package the app? Commented Feb 1, 2019 at 2:50
  • I am following the kivy packaging instructions for Windows kivy.org/doc/stable/guide/packaging-windows.html Commented Feb 2, 2019 at 0:03
  • I am following the kivy packaging instructions for Windows kivy.org/doc/stable/guide/packaging-windows.html I am using Windows 7, python 3.6 in an anaconda environment. The packaging starts as usual, it creates the spec file and empty folders for dist and build. At some point, around the lines of "Processing pre safe import ....six.moves" it stays there for a longer while than usual and suddenly goes very rapidly to several lines of File:.... for different files and finally maximum recursion depth exceeded. I have no idea what is going on or how to approach it. Thank you Commented Feb 2, 2019 at 0:09
  • Possible duplicate of pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object Commented Feb 2, 2019 at 2:04
  • Although the question suggested by John Anderson (thanks for the link) has an answer: import sys sys.setrecursionlimit(5000) at the beginning of the spec file, it does not work because my problem occurss at the first stage of creating the kivy package: python -m PyInstaller --name touchtracer examples-path\demo\touchtracer\main.py and this step overwrites anything I have written on the spec file. Commented Feb 5, 2019 at 0:46

3 Answers 3

2

Thank you so MUCH to everybody who tried to help. I found an answer and I hope it helps other people who tries to create a kivy package and there is a problem importing python module(s).

Once you have your main.py script ready to package:

1.Start with the instructions at

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

and do the first step:

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

This will give you the error of maximum recursion depth exceeded or whatever error this gives to you originally. No worries. The purpose of this step is to create an initial spec file.

2.Open the spec file and add all the extras that the kivy instructions give you at

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

that is:

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

3.In addition to that, add at the beginning of the spec file the following:

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

4.Also add any imports in the hidden imports that you might need.

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

5.Just follow the last step at

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

that is:

python -m PyInstaller touchtracer.spec

and get your app built

Sign up to request clarification or add additional context in comments.

1 Comment

kinda strange , i am facing the same issue. But previously i did not have any such kind of issues. I didn't even need to import kivy.deps and was still able to build. What is causing this issue?
2

This issue is caused by PyInstaller versions above 5.6 which no longer creates a fake sys.stdout/sys.stderr in windowed mode. Instead, both are left as None which matches what pythonw.exe does. If kivy.logger blindly writes to sys.stderr without first checking that it's there then this is kivy's bug. I hope Kivy will include stdout/err check within logger.py soon to be compatible with PyInstaller 5.7.0+

for now you can manually bypass this bug by explicitly setting environment or build with console enabled or downgrade PyInstaller.

Below mentioned snippet should be added before importing kivy.

import os,sys
if sys.__stdout__ is None or sys.__stderr__ is None:
    os.environ['KIVY_NO_CONSOLELOG'] = '1'

Comments

1

When we go into a recursion, there is a risk of stack overflow and the Cpython working under the hood does not take it upon itself to optimize tail recursion, so if you go too deep, you will move closer towards a stack overflow. Generally different Cpython/python flavors have different recursion permit depth, The version of python you have running locally has a more liberal depth limit (Generally because it is assumed developers have good enough computers that this can take place). But when you use tools to package your application they generally override the sys.setrecursionlimit to a more conservative value as they try to make sure you don't cause an stack overflow on systems with lower hardware.

Sadly there is no silver bullet for this problem, you can try to look into your specific manager and change the limit (Not recommended) or you can try to convert your recursive blocks into iterative blocks.

2 Comments

Thank you for your answer anand_v.singh. However, there should be some solution, right? It cannot be that you cannot use such a common module like matplotlib.pyplot in kivy. My code does not have any recursive blocks, which makes it even more surprising as I have tried to explain in point 1 of the question.
@Ivan Try changing the sys.setrecursionlimit flag, You will have to search how to do it exactly for kivy, but it can be done.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.