为什么 PyQt 在没有信息的情况下崩溃?(退出代码 0xC0000409) [英] Why does PyQt crashes without information? (exit code 0xC0000409)
问题描述
我正在尝试使用 PyQt 开发软件,但我经常遇到没有调试信息的软件崩溃(只有退出代码 0xC0000409).我正在使用 QThread,我写了一个这样的系统:
I'm trying to develop a software with PyQt, but I often get stuck on software crashes without debug information (only the exit code 0xC0000409). I'm using QThread, and I wrote a system like this:
class serialThreadC(QThread):
updateOutBox = QtCore.pyqtSignal(str)
updateStatus = QtCore.pyqtSignal(int)
def __init__(self):
super(serialThreadC, self).__init__()
self.ser = False
self.state = 0
self.serialEnabled = False
def run(self):
while True:
if self.state == -3 or self.state == -2:
if self.SerialEnabled:
self.updatePB(20)
elif self.state == 0:
if self.serialEnabled:
self.updatePB(20)
def ConnDisconn(self):
self.serialEnabled = not self.serialEnabled
def updatePB(self, stat):
self.state = stat
self.updateStatus.emit(self.state)
serialThread = serialThreadC()
serialThread.start()
## sw is a QDialog already loaded
serialThread.updateOutBox.connect(sw.updateOutBox)
serialThread.updateStatus.connect(sw.updateStatus)
sw.PB_ConnDisconn.clicked.connect(serialThread.ConnDisconn)
当我在 run()
或 ConnDisconn()
中读/写 serialEnabled
时发生崩溃.我知道 PyQt 不是线程安全的,并且错误处理变量会导致我的类型崩溃,但我无法理解我的代码有什么问题.我的想法(可能是错误的)是所有 serialThread
方法都在同一个线程上执行,如果它们连接到 gui(主线程).错了吗?以同样的方式,我从 serialThread
发出事件并将它们连接到 GUI,但这从来没有给我带来问题.
I have crashes when I read/write serialEnabled
in run()
or in ConnDisconn()
. I know that PyQt is not thread-safe and that a wrong handling of variables gives crashes of my type, but I can't understand what is wrong with my code. My idea (maybe wrong) is that all serialThread
methods are executed on the same thread, also if they are connected to a gui (main thread). Is that wrong? In the same way, I emit events from serialThread
and I connected them to the GUI, but that never gave me problems.
你能看到我犯的错误吗?如果在没有其他信息的情况下发生崩溃,有没有办法调试代码?(我使用的是 PyCharm 2017.1.3).
Can you see the mistake I made? Is there a way to debug the code if there is a crash without other infos? (I use PyCharm 2017.1.3).
推荐答案
PyQt 是线程安全的,与 Qt 是线程安全的程度相同.Qt 文档会告诉您他们的 API 的哪些部分可以保证如此,以及在什么情况下.
PyQt is thread-safe to the same extent that Qt is thread-safe. The Qt docs will tell you which parts of their API are guaranteed to be so, and under what circumstances.
跨线程信号是线程安全的,因此在您的示例中调用 updatePB
方法是可以的.您的 ConnDisconn
方法不是线程安全的,但这与 PyQt 或 Qt 无关 - 这只是您编写它的方式的结果.serialEnabled
属性可以被两个线程同时读/写,所以行为是严格未定义的.一种线程安全的编写方式是使用 mutex,就像这样:
Cross-thread signals are thread-safe, so calling the updatePB
method in your example is okay. Your ConnDisconn
method is not thread-safe, but that has got nothing to do with PyQt or Qt - it's just a consequence of how you wrote it. The serialEnabled
attribute could be read/written by two threads simultaneously, so the behaviour is strictly undefined. A thread-safe way of writing this would be to use a mutex, like so:
class serialThreadC(QThread):
updateOutBox = QtCore.pyqtSignal(str)
updateStatus = QtCore.pyqtSignal(int)
def __init__(self):
super(serialThreadC, self).__init__()
self.ser = False
self.state = 0
self._mutex = QMutex()
self.serialEnabled = False
def ConnDisconn(self):
self._mutex.lock()
self.serialEnabled = not self.serialEnabled
self._mutex.unlock()
def run(self):
while True:
if self.state == -3 or self.state == -2:
self._mutex.lock()
if self.serialEnabled:
self.updatePB(20)
self._mutex.unlock()
elif self.state == 0:
self._mutex.lock()
if self.serialEnabled:
self.updatePB(20)
self._mutex.unlock()
(注意:如果您使用任何类型的 IDE 或调试器,并且遇到意外错误或崩溃,则诊断问题的第一步应该始终是在标准控制台中测试代码.通常,IDE 或调试器本身可能是问题的原因,或者可能掩盖来自 Python 或底层库(例如 Qt)的错误消息).
(NB: if you're using any kind of IDE or debugger, and you are getting unexpected errors or crashes, your first step in diagnosing the problem should always be to test the code in a standard console. Quite often, the IDE or debugger itself can be the cause of the problem, or may mask error messages comming either from Python or from underlying libraries, such as Qt).
这篇关于为什么 PyQt 在没有信息的情况下崩溃?(退出代码 0xC0000409)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!