【问题标题】:PyQT Segmentation fault (sometimes)PyQT 分段错误(有时)
【发布时间】:2014-02-18 15:19:06
【问题描述】:

我正在创建一个接口来管理一些服务器,基本功能,如重启服务和这样的想法,我在QTCreator 中创建了接口,在PyQT5 中进行了编程,它工作正常(有时)。

有时它也能正常工作,有时我得到Segmentation FaultQObject::connect: Cannot queue arguments of type 'QTextCursor' (Make sure 'QTextCursor' is registered using qRegisterMetaType().)

当我在MainWindow 中点击restart_nginx 时会发生这种情况,可能是线程管理有问题,这是我与PyQT/QT 合作的第一个项目

谢谢。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import unicode_literals

import paramiko
import threading

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from ui_mainwindow import Ui_MainWindow

servers = {
    "Mars": "198.58.112.***",
    "Saturn": "198.58.116.***"
}

green = "rgb(83, 236, 17)"
default = "rgb(154, 154, 154)"
yellow = "yellow"
red = "red"
pw = 'pass'

def format_status(color):
    return "background-color: " + color + "; border: 1px solid black;"

class Worker(QObject):

    def __init__(self, ui, server, command=None, sudo=False, *args, **kwargs):
        QObject.__init__(self, *args, **kwargs)

        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        self.ui = ui
        self.command = command
        self.sudo = sudo
        self.server = server

    finished = pyqtSignal()

    @pyqtSlot()
    def execute(self):

        self.ui.status_restart_nginx.setStyleSheet(format_status(color=yellow))

        try:

            self.ssh.connect(self.server, username='hercules', password=pw)

        except paramiko.SSHException as e:

            self.ui.log.append("ERRO: Impossible to connect: %s", e)
            self.ui.status_restart_nginx.setStyleSheet(format_status(color=red))

        try:

            session = self.ssh.get_transport().open_session()
            session.get_pty()

            f = session.makefile()

            session.exec_command("ls -lh")

            #if self.sudo:
            #    session.send(pw + '\n')

            for line in f.readlines():
                self.ui.log.append(line)

            f.close()

            self.ssh.close()

            self.ui.status_restart_nginx.setStyleSheet(format_status(color=green))

        except Exception as e:
            self.ui.status_restart_nginx.setStyleSheet(format_status(color=red))
            print 'errinho: ', e

        self.finished.emit()

class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None, **kwargs):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.btn_restart_nginx.clicked.connect(self.restart_nginx)

        self.thread_worker = None
        self.obj_worker = None

    def create_worker(self, server, command=None, sudo=False):

        self.thread_worker = QThread(parent = self)
        self.obj_worker = Worker(ui = self, server = server, command = command, sudo = sudo)
        self.obj_worker.moveToThread(self.thread_worker)
        self.obj_worker.finished.connect(self.thread_worker.quit)
        self.thread_worker.started.connect(self.obj_worker.execute)
        self.thread_worker.start()

    def restart_nginx(self):

        self.status_restart_nginx.setStyleSheet(format_status(color=yellow))

        self.log.append("(Mars) Nginx: trying to restart front-end...")

        self.create_worker(servers["Mars"], command = "sudo service nginx restart", sudo = True)

if __name__=="__main__":

    from sys import argv, exit

    app = QApplication(argv)

    m = MainWindow()
    m.show()
    m.raise_()

    exit(app.exec_())

【问题讨论】:

  • 也许先用谷歌搜索错误信息;)

标签: python multithreading qt pyqt pyqt5


【解决方案1】:

切勿尝试从工作线程中更改 GUI。只在主 GUI 线程中更新 GUI,并且不要将 GUI 元素的引用传递给工作线程。

在 GUI 线程和工作线程之间进行通信的最简单和最安全的方法是发出 custom signals。当信号以这种方式为emitted across threads时,它们会被排队,一旦控制返回到它的事件循环,就会在接收者的线程中调用槽。

在 PyQt 中,通常还建议在跨线程建立连接时使用 pyqtSlot decorator,原因在 this answer 中列出。

【讨论】:

    猜你喜欢
    • 2013-05-21
    • 2017-02-21
    • 2017-04-14
    • 2018-03-27
    • 2014-03-09
    • 1970-01-01
    • 2016-11-29
    • 2020-07-14
    • 2015-06-09
    相关资源
    最近更新 更多