-1

编辑:尝试了用 cython 编译的 pyqt5 的等效代码。它工作得很好,所以这似乎是一个 pyside2 错误。

最新版本的 cython。当我用 python 运行它时,我的应用程序运行良好,但是当我将它变成一个模块并从一个简单的启动器脚本中导入模块时,它似乎没有看到来自互联网的任何数据,它也给了我这些:RecursionError:最大调用 Python 对象时超出递归深度。

Nuitka 有同样的问题,但没有给我这些递归错误。

我不知道它是否相关,但是在使用 gcc 编译程序(制作目标代码)时,我也得到了这个错误/警告/注释(唯一的一个):

$ 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) {
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

也不确定是否相关,但我有一堆类(线程)在一个完成循环时调用下一个类。即使它在 python 中工作正常,也许这是一个 nono?

我正在使用 pyside2、请求、delorean 和人性化。我什至不知道如何开始调试,这是一个 4000 行的程序。

编辑:好的,所以我设法在一个最小的例子中重现了确切的问题。在使用 cython 或 nuitka 编译之前,此代码将完美运行。如果你用 cython 编译它,它会输出:

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

并挂起,但它会显示窗口内容。使用 nuitka 它永远不会显示窗口的内容,但线程将按预期运行。如果有人能解释它为什么会发生以及我如何解决它,那就太好了:

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

1 回答 1

2

每个环境中可能存在不同的递归限制设置。尝试调整递归限制

import sys
sys.setrecursionlimit(3000)

(3000 只是一个猜测)。您可以通过使用查看限制

import sys
sys.getrecursionlimit()

这只是一种技巧,不是推荐的方式。您应该考虑使用迭代而不是递归来重构代码,或者使递归更好地工作。通过提供的信息很难说出更多信息。

我见过其他人也像这样设置递归深度:Setting stacksize in a python script。也许它也值得一试。

更新:更新问题后,我发现您也遇到了可变跟踪大小的问题。您也可以尝试:调整可变跟踪分配长度

于 2018-05-29T11:06:01.070 回答