When i compile my python code i get: RecursionErro

2019-09-20 16:07发布

edit: Tried the equivalent code with pyqt5 compiled with cython. It works swimmingly so this seems to be a pyside2 bug.

Latest version of cython. My app works fine when i run it with python but when i make it into a module and import the module from a simple launcher script suddenly it doesn't seem to see any data from the internet and it also gives me these: RecursionError: maximum recursion depth exceeded while calling a Python object.

Nuitka has the same problem but doesn't give me these recursionerrors.

I have no idea if it's relevant but when compiling the program(making object code) with gcc i also get this error/warning/note(the only one):

$ python setup.py build_ext --inplace
Compiling prog.py because it changed.
[1/1] Cythonizing prog.py
running build_ext
building 'prog' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 
-Wall -Wstrict-prototypes -march=x86-64 -mtune=generic -O2 -pipe -
fstack-protector-strong -fno-plt -march=x86-64 -mtune=generic -O2 -
pipe -fstack-protector-strong -fno-plt -march=x86-64 -mtune=generic -
O2 -pipe -fstack-protector-strong -fno-plt -fPIC -
I/usr/include/python3.6m -c prog.c -o build/temp.linux-x86_64-
3.6/prog.o
prog.c: In function ‘__pyx_pf_4prog_13Ui_MainWindow_setupUi.isra.76’:
prog.c:41235:18: note: variable tracking size limit exceeded with -
fvar-tracking-assignments, retrying without
static PyObject *__pyx_pf_4prog_13Ui_MainWindow_setupUi(CYTHON_UNUSED 
PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_MainWindow) {
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Also not sure if relevant but i have a bunch of classes(threads) that calls the next class when one is finished making a loop. Maybe this is a nono even if it works fine in python?

I'm using pyside2, requests, delorean and humanize. Im not even sure how to start debugging this, it's a 4000 line program.

edit: Ok so i managed to reproduce the exact problem in a minimal example. This code will work perfectly before you compile it with cython or nuitka. If you compile it with cython it will output:

('thread1:', <Response [200]>)
RecursionError: maximum recursion depth exceeded while calling a Python object

and hang but it will show the window contents. With nuitka it will never show the contents of the window but the threads will run as expected. If anyone can explain why it happens and how i can fix it that would be great:

from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Slot, Signal, QThread
import sys
import requests

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(240, 100, 97, 34))
        self.pushButton.setObjectName("pushButton")
        self.plainTextEdit = QtWidgets.QPlainTextEdit(self.centralwidget)
        self.plainTextEdit.setGeometry(QtCore.QRect(200, 160, 451, 271))
        self.plainTextEdit.setPlainText("")
        self.plainTextEdit.setObjectName("plainTextEdit")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "OK"))

class MainUIClass(QtWidgets.QMainWindow, Ui_MainWindow):
    def closeEvent(self, evnt):
        print("CLOSED")
        self.thread1.quit()
        self.thread2.quit()
        self.thread3.quit()
        self.thread1.wait()
        self.thread2.wait()
        self.thread3.wait()
        print("thread1 is running?:", self.thread1.isRunning())
        print("thread2 is running?:", self.thread2.isRunning())
        print("thread3 is running?:", self.thread3.isRunning())
        sys.exit()

    def __init__(self, parent=None):
        super().__init__()
        self.setupUi(self)

        self.thread1 = QThread()
        self.thread2 = QThread()
        self.thread3 = QThread()

        self.Class1 = Class1()
        self.Class2 = Class2()
        self.Class3 = Class3()

        self.Class1.moveToThread(self.thread1)
        self.Class2.moveToThread(self.thread2)
        self.Class3.moveToThread(self.thread3)

        self.thread1.started.connect(lambda: self.Class1.startThread())

        self.Class1.startThread2.connect(self.Class2.startThread)
        self.Class2.startThread3.connect(self.Class3.startThread)
        self.Class3.startThread1.connect(self.Class1.startThread)

        self.thread1.start()
        self.thread2.start()
        self.thread3.start()

class Class1(QtCore.QObject):
    startThread2 = Signal()

    def __init__(self):
        super().__init__()

    def startThread(self):
        data = requests.get("https://www.google.com")
        print("thread1:", data)
        self.startThread2.emit()

class Class2(QtCore.QObject):
    startThread3 = Signal()

    def __init__(self):
        super().__init__()

    def startThread(self):
        data = requests.get("https://www.google.com")
        print("thread2:", data)
        self.startThread3.emit()

class Class3(QtCore.QObject):
    startThread1 = Signal()

    def __init__(self):
        super().__init__()

    def startThread(self):
        data = requests.get("https://www.google.com")
        print("thread3:", data)
        self.startThread1.emit()

a = QtWidgets.QApplication(sys.argv)
app = MainUIClass()

a.setQuitOnLastWindowClosed(False)
app.setWindowTitle("Pyside2 thread compiled test")
app.show()

sys.exit(a.exec_())

1条回答
放荡不羁爱自由
2楼-- · 2019-09-20 17:00

It is possible that there are different settings of recursion limit in each environment. Try to adjust the recursion limit

import sys
sys.setrecursionlimit(3000)

(3000 is just a guess). You can see the limit by using

import sys
sys.getrecursionlimit()

This is only a hack, not a recommended way. You should think to refactor code using iteration instead of recursion or make the recursion work better. It's hard to tell more with provided information.

I've seen others setting also recursion depths like this: Setting stacksize in a python script . Maybe it's worth a try, too.

UPDATE: After you have updated your question, I've seen that you also have problems with variable tracking size. You can also try that: Adjust Variable Tracking Assignment Length

查看更多
登录 后发表回答