编辑:尝试了用 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_())