i'm creating one interface to manage some servers, the basic functions like restarting services and thinks like that, I made the interface in QTCreator
and the programming in PyQT5
, it's working properly (sometimes).
Sometimes it just work as well, other times i get Segmentation Fault
or QObject::connect: Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType().)
It happen when I hit restart_nginx
in MainWindow
, maybe some problem with thread management, it's the first project that i'm working with PyQT/QT
Thank you.
#!/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_())
Never attempt to make changes to the GUI from within a worker thread. Only ever update the GUI from within the main GUI thread, and do not pass references to GUI elements to the worker thread.
The simplest and safest way to communicate between the GUI thread and the worker thread is to emit custom signals. When signals are emitted across threads in this way, they are queued, and the slot will be invoked in the receiver's thread once control returns to it's event-loop.
In PyQt, it is also generally advisable to use the pyqtSlot decorator when making connections across threads, for the reasons outlined in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With