簡體   English   中英

QThread在Python中的使用

[英]QThread use in Python

我在用Python編寫更大的程序方面還很陌生(以前我只是寫短腳本)。 我要編寫的程序從外部設備接收數據,將其保存到數據庫並在GUI中(連續)顯示。 由於處理數據非常耗時,因此我想使用線程(具體來說是PySide QtCore QThreads)。 我能想到的最好的方法是設置兩個線程,一個用於數據庫進程,一個用於處理串行端口,並且在MainThread中運行GUI。 現在,我已經閱讀了很多有關正確/不正確的QThreading的知識,從Maya的帖子開始,然后進行更深入的研究,直到發現該帖子為止:

什么時候子類化,什么時候不子類化?

如果您確實不需要線程中的事件循環,則應該子類化。 如果需要事件循環並處理線程中的信號和插槽,則可能不需要子類化。

問題1:現在我不知道的第一件事是走哪條路(是否可以繼承)。 從(Question2)開始,我的猜測是子類化,但是我不確定,現在我moveToThread()堅持moveToThread()

問題2:我不知道的另一件事是如何使線程中的操作受事件驅動(SerialThread從設備接收數據,通過信號將其發送到DatabaseThread,DatabaseThread收集數據並將其放入數據庫)。

問題3:使用moveToThread() AttributeError: 'PySide.QtCore.QThread' object has no attribute 'my_awesome_method'為我為類編寫的每個方法的AttributeError: 'PySide.QtCore.QThread' object has no attribute 'my_awesome_method' 對我來說很明顯,我不了解這里的操作原理。 在使用my_class.moveToThread(my_thread)時,如何實現希望my_class擁有的方法?

我已經找到了關於QThreads和C ++的所有教程,因此關於Python中的QThreads的討論很有趣,但是並不能解釋我想知道的所有內容。 我需要一個帶有信號,插槽和如何使用run()的確切說明的簡單示例。 我會裝飾嗎? 為什么? 怎么樣? 它是如何工作的?

我的代碼的簡短版本如下所示:

from PySide import QtCore
from app.thrads.gui.gui import Gui            #my own class
from app.threads.db.db import Database        #my own class
from app.threads.serial.serial import Serial  #my own class

class AppManager():
    def __init__(self):
        self.gui = Gui()

        self.db = Database()
        self.db_thread = QtCore.QThread()
        self.db.moveToThread(self.db_thread)
        self.db_thread.start()

        self.serial = Serial()
        self.serial_thread = QtCore.QThread()
        self.serial.moveToThread(self.serial_thread)
        self.serial_thread.start()

我的數據庫和串行類看起來像這樣:

from PySide import QtCore
from .db_signal import DbSignal

class Database(QtCore.QObject):
    def __init__(self):
        super(Database, self).__init__()
        self.signal = DbSignal()

    def my_awesome_method(self):
        ''' does something awesome '''
        pass

問題1

我認為最好的方法是最簡單的:不要子類化,只需創建兩個不同的線程即可。 在第一個中,移動Database對象,在第二個中,移動Serial對象。 這樣一來,您就不會在實現子類線程的過程中犯錯誤,並且錯誤修復會更快。


問題2

我不知道您的應用程序的體系結構,但是在創建線程並在其中移動工作對象之后,您可以按照以下步驟進行操作:

self.serial_thread.started.connect(self.serial.start)
self.serial_thread.finished.connect(self.serial.stop)

self.db_thread.started.connect(self.db.start)
self.serial_thread.finished.connect(self.db.stop)

self.serial.data_ready.connect(self.db.handle_new_data)

# Starting the database first, as it we won't lose a single packet of data
self.db_thread.start()
self.serial_thread.start()

實際上,QThreads的優點是它們實際上並沒有修改代碼。


問題3

我認為問題是您正在嘗試使用QThread調用my_awesome_method ,數據庫或串行偵聽器已移至該my_awesome_method 相反,您應該使用對象本身來調用該方法,就好像它不在另一個線程中一樣!

# Bad!
obj.moveToThread(thread)
thread.method_of_obj(param)

# Good!
obj.moveToThread(thread)
obj.method_of_obj(param)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM