亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

python multiprocessing - 將子進程日志發送到在父進程中運行的 GUI

python multiprocessing - 將子進程日志發送到在父進程中運行的 GUI

aluckdog 2021-08-17 10:44:28
我正在編寫的一些分析代碼之上構建一個界面,該代碼執行一些 SQL 并處理查詢結果。在我想向用戶公開的這個分析代碼中,有許多事件的日志記錄。因為分析代碼運行時間相當長,而且我不希望 UI 被阻塞,所以到目前為止我是通過將分析函數放入自己的線程來完成的。我現在擁有的簡化示例(完整腳本):import sysimport timeimport loggingfrom PySide2 import QtCore, QtWidgetsdef long_task():    logging.info('Starting long task')    time.sleep(3) # this would be replaced with a real task    logging.info('Long task complete')class LogEmitter(QtCore.QObject):    sigLog = QtCore.Signal(str)class LogHandler(logging.Handler):    def __init__(self):        super().__init__()        self.emitter = LogEmitter()    def emit(self, record):        msg = self.format(record)        self.emitter.sigLog.emit(msg)class LogDialog(QtWidgets.QDialog):    def __init__(self, parent=None):        super().__init__(parent)        log_txt = QtWidgets.QPlainTextEdit(self)        log_txt.setReadOnly(True)        layout = QtWidgets.QHBoxLayout(self)        layout.addWidget(log_txt)        self.setWindowTitle('Event Log')        handler = LogHandler()        handler.emitter.sigLog.connect(log_txt.appendPlainText)        logger = logging.getLogger()        logger.addHandler(handler)        logger.setLevel(logging.INFO)class Worker(QtCore.QThread):    results = QtCore.Signal(object)    def __init__(self, func, *args, **kwargs):        super().__init__()        self.func = func        self.args = args        self.kwargs = kwargs    def run(self):        results = self.func(*self.args, **self.kwargs)        self.results.emit(results)class MainWindow(QtWidgets.QMainWindow):這工作正常,除了我需要能夠允許用戶停止執行分析代碼。我讀過的一切都表明沒有辦法很好地中斷線程,所以使用multiprocessing庫似乎是要走的路(沒有辦法重新編寫分析代碼以允許定期輪詢,因為大部分時間是只花等待查詢返回結果)。通過使用multiprocessing.Pool和以不阻塞 UI 的方式執行分析代碼,很容易獲得相同的功能apply_async。但我似乎無法弄清楚如何從子進程檢索日志輸出并將其傳遞給父進程以更新日志對話框。我已經閱讀了幾乎所有關于此的 SO 問題以及如何處理從多個進程寫入單個日志文件的食譜示例,但我無法圍繞如何使這些想法適應我的想法我想在這里做。
查看完整描述

2 回答

?
繁星淼淼

TA貢獻1775條經驗 獲得超11個贊

信號不會在進程之間傳輸數據,因此對于這種情況,必須使用管道然后發出信號:


# other imports

import threading

# ...


class LogHandler(logging.Handler):

    def __init__(self):

        super().__init__()

        self.r, self.w = multiprocessing.Pipe()

        self.emitter = LogEmitter()

        threading.Thread(target=self.listen, daemon=True).start()


    def emit(self, record):

        msg = self.format(record)

        self.w.send(msg)


    def listen(self):

        while True:

            try:

                msg = self.r.recv()

                self.emitter.sigLog.emit(msg)

            except EOFError:

                break


# ...


查看完整回答
反對 回復 2021-08-17
  • 2 回答
  • 0 關注
  • 399 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號