【发布时间】:2020-06-30 21:20:38
【问题描述】:
基于here 和here 的代码,我在PyQt5 中迈出了多线程的第一步。启动程序后,出现图形用户界面,但几秒钟后它崩溃并出现以下错误
Process finished with exit code -1073740791 (0xC0000409)
在谷歌搜索错误消息后,我比较确定多线程有问题。不幸的是,我不知道错误是什么以及如何修复。
代码
import sys
from datetime import datetime
import wmi
from PyQt5. QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QHeaderView
class KeyboardDetectorSignals(QObject):
keyboard_changed = pyqtSignal(str)
class KeyboardDetector(QRunnable):
def __init__(self):
super().__init__()
self.signals = KeyboardDetectorSignals()
def run(self):
device_connected_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"
device_disconnected_wql = "SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"
c = wmi.WMI()
connected_watcher = c.watch_for(raw_wql=device_connected_wql)
disconnected_watcher = c.watch_for(raw_wql=device_disconnected_wql)
while True:
try:
connected = connected_watcher(timeout_ms=10)
except wmi.x_wmi_timed_out:
pass
else:
if connected:
self.signals.keyboard_changed.emit("Keyboard connected.")
try:
disconnected = disconnected_watcher(timeout_ms=10)
except wmi.x_wmi_timed_out:
pass
else:
if disconnected:
self.signals.keyboard_changed.emit("Keyboard disconnected.")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 500, 500)
self.setWindowTitle("Keyboard Logger")
self.log_table = QTableWidget()
self.log_table.setColumnCount(2)
self.log_table.setShowGrid(True)
self.log_table.setHorizontalHeaderLabels(["Time", "Event"])
self.log_table.horizontalHeader().setStretchLastSection(True)
self.log_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.setCentralWidget(self.log_table)
self.show()
self.threadpool = QThreadPool()
keyboard_detector = KeyboardDetector()
keyboard_detector.signals.keyboard_changed.connect(self.add_row)
self.threadpool.start(keyboard_detector)
def add_row(self, event: str):
now = datetime.now()
datetime_string = now.strftime("%Y-%m-%d %H:%M:%S")
row_count = self.log_table.rowCount()
self.log_table.insertRow(row_count)
self.log_table.setItem(row_count, 0, QTableWidgetItem(datetime_string))
self.log_table.setItem(row_count, 1, QTableWidgetItem(event))
def main():
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
更新 1: 删除了 @pyqtSlot()。
从 CMD 运行脚本时出现以下错误:
Traceback (most recent call last):
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1340, in connect
obj = GetObject(moniker)
File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 72, in GetObject
return Moniker(Pathname, clsctx)
File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 87, in Moniker
moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
pywintypes.com_error: (-2147221020, 'Ung³ltige Syntax', None, None)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1354, in connect
handle_com_error()
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 258, in handle_com_error
raise klass(com_error=err)
wmi.x_wmi_uninitialised_thread: <x_wmi: Unexpected COM Error (-2147221020, 'Ung³ltige Syntax', None, None)>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "main.py", line 26, in run
c = wmi.WMI()
File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1357, in connect
raise x_wmi_uninitialised_thread("WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex]")
wmi.x_wmi_uninitialised_thread: <x_wmi: WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex] (no underlying exception)>
PS C:\Users\ata\PycharmProjects\Snippets\KeyboardLogger>
【问题讨论】:
-
您能否从 CMD 运行脚本以获得更具描述性的错误消息?同时删除
pyqtSlot -
@eyllanesc 请参阅更新 1。
-
添加
import pythoncom并在device_connected_wql = "SELECT ...之前添加pythoncom.CoInitialize() -
@eyllanesc 太棒了!使用 pythoncom 已经解决了这个问题。
pythoncom这个模块我从来没听说过,更别说用过了。
标签: python pyqt pyqt5 python-multithreading