【问题标题】:Pyqt5 threading can't work (Fatal Python error: could not acquire lock)Pyqt5 线程无法工作(致命的 Python 错误:无法获取锁)
【发布时间】:2018-12-18 22:32:52
【问题描述】:

我已经阅读了大量关于此的 QThread 教程和 SO Answers。但我不能让我的线程工作。大多数时候,它只运行一次或打印错误消息。如果我在应用程序启动后立即启动线程,但我希望线程在某个函数之后运行,因为我想先设置目录位置。

文件结构是这样排列的:

App.py
Controllers/
    main_controller.py
    recorder.py
Model/
    model.py
Views/
    main_view.py

App.py

import sys
from PyQt5.QtWidgets import QApplication

from Model.model import Model
from Controllers.main_controller import MainController
from Views.main_view import MainView


class App(QApplication):
    def __init__(self, sys_argv):
        super().__init__(sys_argv)
        self.model = Model()
        self.main_controller = MainController(self.model)
        self.main_view = MainView(self.model, self.main_controller)


if __name__ == "__main__":
    app = App(sys.argv)
    sys.exit(app.exec_())

model.py

from PyQt5.QtCore import QObject


class Model(QObject):
    def __init__(self):
        super().__init__()
        self.directory = ""

    def get_directory(self):
        return self.directory

    def set_directory(self, directory):
        self.directory = directory

ma​​in_view.py

from PyQt5.QtWidgets import QMenu, QSystemTrayIcon, QMainWindow, QFileDialog
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication
from Controllers.recorder import Recorder


class MainView(QMainWindow):

    def __init__(self, model, main_controller):
        super().__init__()

        self._model = model
        self._main_controller = main_controller

        # UI
        icon = QtGui.QIcon("icon24x24.png")
        menu = QMenu()
        start_action = menu.addAction("Start Recording")
        stop_action = menu.addAction("Stop Recording")
        self.tray = QSystemTrayIcon()
        self.tray.setIcon(icon)
        self.tray.setContextMenu(menu)
        self.tray.show()

        start_action.triggered.connect(self.start_app)
        stop_action.triggered.connect(self.stop_app)

        self.recordThread = Recorder()

    def start_app(self):
        directory = QFileDialog.getExistingDirectory(self, "Select Directory")
        self._main_controller.set_directory(directory)
        self.start_thread()

    def start_thread(self):
        self.recordThread.start()

    def stop_app(self):
        self.recordThread.terminate()
        QApplication.instance().quit()
        print("app stopped")

ma​​in_controller.py

from PyQt5.QtCore import QObject


class MainController(QObject):

    def __init__(self, model):
        super().__init__()
        self._model = model

    def set_directory(self, directory):
        self._model.set_directory(directory)

recorder.py

import time
from PyQt5.QtCore import QThread, QTimer, pyqtSignal
from Model.model import Model


class Recorder(QThread):

    job_done = pyqtSignal()

    def __init__(self):
        QThread.__init__(self)
        self._model = Model()

    def __del__(self):
        self.wait()

    def run(self):
        while True:
            print("I am the loop")
            print(self._model.get_directory())
            # time.sleep(4 - time.time() % 4)
            QThread.sleep(4)
            print("now is {}".format(time.time()))
        self.job_done.emit()

我根据各种教程尝试使用各种样式,包括 Qthread、QObject、pyqtsignal。但没有什么对我有用。它要么只是打印“我是循环”然后退出。或打印

I am the loop
Fatal Python error: could not acquire lock for <_io.BufferedWriter name='<stdout>'> at interpreter shutdown, possibly due to daemon threads

Thread 0x00007f5d1bfff700 (most recent call first):
  File "/App/Controllers/recorder.py", line 20 in run

Current thread 0x00007f5d3458f700 (most recent call first):
Aborted

谢谢

【问题讨论】:

  • 显示main_controller.py
  • 天哪,我已经添加了。
  • 我看到的唯一错误是您正在创建 2 个模型而不是共享,以更正此更改:Recorder.py def __init__(self):def __init__(self, model):; self._model = Model()self._model = modelmain_view.pyself.recordThread = Recorder()self.recordThread = Recorder(model)
  • 你是如何运行应用程序的?在终端还是在某些 IDE 中?
  • 根据您的建议,我有corrected,没有任何效果。我从终端运行应用程序。

标签: python pyqt5 qthread


【解决方案1】:

您的代码没有问题。该应用程序在调用QFileDialog.getExistingDirectory 后立即关闭,因为这是 Qt 的特性。

当所有窗口关闭时Qt退出

应用已关闭,因为您不再有任何窗口。您的应用程序没有任何窗口,但 QSystemTrayIcon()。将setQuitOnLastWindowClosed() 设置为 False 即可解决问题。

yourApp.setQuitOnLastWindowClosed(False)

Source

【讨论】:

    猜你喜欢
    • 2020-07-24
    • 2012-11-09
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 2020-03-18
    • 2020-05-02
    • 1970-01-01
    • 2015-06-22
    相关资源
    最近更新 更多