Mecanismo de excepción de Python, multiproceso y QTimer en PyQt5, multiproceso

1. Mecanismo de manejo de excepciones

def test(x):
    try: y = 10 / x print(y) #except Exception as e: #print(e) #可以打印出异常的类型 except ZeroDivisionError: #抛出异常,执行下面的程序,如果是界面软件可以弹出一个窗口,提示用户输入错误 print(x) else: #如果程序不存在异常,则执行该程序 print(100 / x) finally: print('the program end') #不管程序是否错误,始终都会执行 test(0) # 0 # the program end test(1) # 10.0 # 100.0 # the program end 
def test2(): 
    try: assert False, 'error' except: print('another') # 输出 another def myLevel(level): if level < 1: raise ValueError('Invalid level', level) #自定义异常 try: myLevel(0) except ValueError: print('level < 1') #输出 :level < 1 print('test 2--') test2()

2. Multiproceso

Introducir archivos de biblioteca multiproceso: importar multiprocesamiento 

Para las pruebas multiproceso, debe probar en la función principal principal para
 crear una clase de proceso: Proceso ([grupo [, destino [, nombre [, args [, kwargs]]]]]]), destino representa el objeto que llama y args representa el objeto que llama Tupla de parámetros posicionales. kwargs representa un diccionario de objetos de llamada. El nombre es un alias. El grupo esencialmente no se usa.
 Métodos: is_alive (), join ([timeout]), run (), start (), terminate (). Entre ellos, Process inicia un proceso con start ().
 Atributos: authkey, daemon (se establecerá mediante start ()), código de salida (el proceso es Ninguno en tiempo de ejecución, si es –N, significa que finaliza con la señal N), nombre, pid El daemon finaliza automáticamente después de que finaliza el proceso principal, y no puede crear un nuevo proceso por sí mismo, debe establecerse antes de start ()

Daemon es un proceso de daemon: el daemon finaliza automáticamente después de que finaliza el proceso principal, y no puede crear un nuevo proceso por sí mismo, debe establecerse antes de start (). # Después de que se complete la ejecución del subproceso principal, independientemente de si se completa la ejecución del subproceso secundario, finalizará con el subproceso principal.

def worker_1():
    print('this is worker 1') time.sleep(3) print('worker 1 end') # n = 3 # while n > 0: # print("The time is {0}".format(time.ctime())) # time.sleep(interval) # n -= 1 def worker_2(): print('this is worker 2') time.sleep(3) print('worker 2 end') def worker_3(): print('this is worker 3') time.sleep(3) print('worker 3 end') if __name__ == "__main__": p1 = multiprocessing.Process(target = worker_1, args = ()) p2 = multiprocessing.Process(target = worker_2, args = ()) p3 = multiprocessing.Process(target = worker_3, args = ()) # p1.daemon = True # 设置子程序为 守护进程, 主程序结束后,它就随之结束(即如果没有join函数,将不执行worker1函数), 需要放在start 前面 p1.start() #进程调用 start 的时候,将自动调用 run 函数 p2.start() p3.start() #运行3 个worker 程序花费的时间为3 s, 使用了3 个进程进行处理 p1.join() p2.join() p3.join() #添加 join 函数, 先执行 worker 函数, 再执行主进程函数 for p in multiprocessing.active_children(): #这是主进程函数 print('name is :' + p.name + 'pid is :' + str(p.pid) + 'is _alive: '+ str(p.is_alive())) print('电脑的核数'+ str(multiprocessing.cpu_count())) # 电脑的核数4 print('end----')

Salida:

#---没有 join 函数---
# name is :Process-1pid is :6488is _alive: True
# name is :Process-2pid is :5660is _alive: True
# name is :Process-3pid is :7776is _alive: True
# 电脑的核数4
# end----
# this is worker 1
# this is worker 2
# this is worker 3
# worker 1 end
# worker 2 end
# worker 3 end    
 
#---有 join 函数---   等待所有子进程结束,再执行主进程
# this is worker 1
# this is worker 2
# this is worker 3
# worker 1 end
# worker 2 end
# worker 3 end
# 电脑的核数4    #此时执行完线程, active_children() 为空
# end----  

Al usar múltiples procesos para acceder a recursos compartidos, debe usar Bloquear para evitar conflictos de acceso

def worker_first(lock, f):
    with lock: with open(f, 'a+') as t: #with 自动关闭文件 n = 3 while n > 0: t.write('first write ---') n -= 1 def worker_second(lock, f): lock.acquire() #获取锁 try: with open(f, 'a+') as t: n = 3 while n > 0: t.write('second write ---') n -= 1 finally: lock.release() #使用异常机制,保证最后释放锁 def myProcess(): lock = multiprocessing.Lock() f = r'D:\myfile1.txt' p1 = multiprocessing.Process(target=worker_first, args=(lock, f, )) p2 = multiprocessing.Process(target=worker_second, args=(lock, f, )) p1.start() p2.start() print('end -----------') if __name__ == '__main__': myProcess()

Salida:

first write ---first write ---first write ---second write ---second write ---second write ---

Grupo de procesos

Cuando el grupo de procesos 
 usa Python para la administración del sistema, especialmente cuando se operan múltiples directorios de archivos al mismo tiempo, o se controlan de manera remota múltiples hosts, la operación en paralelo puede ahorrar mucho tiempo. Cuando el número de objetos que se operan no es grande, puede usar directamente el Proceso en multiprocesamiento para generar dinámicamente múltiples procesos, una docena más o menos, pero si son cientos o miles de objetivos, es demasiado para limitar manualmente el número de procesos. Si es demasiado engorroso,
 puede desempeñar el papel del grupo de procesos en este momento. El grupo puede proporcionar un número específico de procesos para que los usuarios llamen. Cuando se envía una nueva solicitud al grupo, si el grupo no está lleno, se creará un nuevo proceso para ejecutar la solicitud; pero si el número de procesos en el grupo Ha alcanzado el máximo especificado,
 entonces la solicitud esperará, hasta que finalice un proceso en el grupo, no creará un nuevo proceso para él.
 
apply_async (func [, args [, kwds [, callback]]]) no es bloqueante, apply (func [, args [, kwds]]) es bloqueante

Grupo de proceso de bloqueo y no bloqueo

Una sola función utiliza un grupo de subprocesos:

def func(msg):
    print('msg is :' + msg) time.sleep(2) print(msg + ' end') return msg + ' re' if __name__ == '__main__': pool = multiprocessing.Pool(processes=3) #创建进程池 result = [] for i in range(4): msg = '%d'%(i) # result.append(pool.apply_async(func, (msg, ))) pool.apply_async(func, (msg, )) #非阻塞进程池, 维持总的进程数为 processes=3, 当一个进程结束后,添加另一个进程进去 # pool.apply(func, (msg, )) #阻塞进程池 print('start------') pool.close() # close 函数需要在 join 函数之前, 关闭进程池后,没有进程加入到pool中 pool.join() # join函数等待所有子进程结束 print('all program done') # print([re.get() for re in result]) #获取结果

Salida:

#---非阻塞进程池 输出------
# start------
# msg is :0
# msg is :1
# msg is :2
# 0 end
# msg is :3
# 1 end
# 2 end
# 3 end
# all program done    
#---阻塞进程池 输出------ 顺序执行
# msg is :0
# 0 end
# msg is :1
# 1 end
# msg is :2
# 2 end
# msg is :3
# 3 end
# start------
# all program done

Grupo de subprocesos para múltiples funciones

def f1():
    result = 0 print('this is one') for i in range(100000): result += i return result def f2(): result = 1 print('this is two') for i in range(2, 100000): result *= i return result if __name__ == '__main__': start = time.time() myPool = multiprocessing.Pool(processes=2) result = [] print('start----') myFunc = [f1, f2] for f in myFunc: result.append(myPool.apply_async(f)) #将输出结果保存到列表中 myPool.close() myPool.join() print([re.get() for re in result]) end = time.time() print('花费的时间: ' + str(end-start)) #huafei de 时间: 8.397480010986328 print('end------')

Usando la función get (), también puede obtener la estructura de datos de los pandas;

def f1():
    result = 0 print('this is one') result = pd.DataFrame(np.arange(16).reshape(-1, 4)) return result # for i in range(100000): # result += i # return result def f2(): result = 1 print('this is two') result = pd.DataFrame(np.arange(9).reshape(-1, 3)) return result # for i in range(2, 100000): # result *= i # return result if __name__ == '__main__': start = time.time() myPool = multiprocessing.Pool(processes=2) result = [] print('start----') myFunc = [f1, f2] for f in myFunc: result.append(myPool.apply_async(f)) #将输出结果保存到列表中 myPool.close() myPool.join() for re in result: print(re.get())

 Resultado de salida:

start----
this is one
this is two
    0   1   2   3
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15
   0  1  2
0  0  1  2
1  3  4  5
2  6  7  8
花费的时间: 0.9370532035827637
end------

 

3. Módulo QTimer en PyQt5

La aplicación de subprocesos múltiples en pyqt5, la tecnología de subprocesos múltiples incluye 3 métodos: 1. Usar el temporizador QTimer, 2. Usar el módulo de subprocesos múltiples QThread, 3. Usar la función de procesamiento de eventos
1. Usar el módulo QTimer, crear una instancia de QTimer, la señal de tiempo de espera Conéctese a la función de ranura y llame a la señal de tiempo de espera. El tiempo self.timer.start (1000) se
introduce en milisegundos
desde PyQt5.QtCore import QTimer, QDateTime

def timerTest():
    class WinForm(QWidget): def __init__(self,parent=None): super(WinForm,self).__init__(parent) self.setWindowTitle("QTimer demo") self.listFile= QListWidget() self.label = QLabel('显示当前时间') self.startBtn = QPushButton('开始') self.endBtn = QPushButton('结束') layout = QGridLayout(self) # 初始化一个定时器 self.timer = QTimer(self) # showTime()方法 self.timer.timeout.connect(self.showTime) # layout.addWidget(self.label,0,0,1,2) layout.addWidget(self.startBtn,1,0) layout.addWidget(self.endBtn,1,1) self.startBtn.clicked.connect( self.startTimer) #首先按下start开始计时,到了2s后,触发timeout 信号 self.endBtn.clicked.connect( self.endTimer) self.setLayout(layout) QTimer.singleShot(5000, self.showmsg) #给定的时间间隔后,调用一个槽函数来发射信号 def showmsg(self): QMessageBox.information(self, '提示信息', '你好') def showTime(self): # 获取系统现在的时间 time = QDateTime.currentDateTime() #获取当前时间 # 设置系统时间显示格式 timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd") # 在标签上显示时间 self.label.setText( timeDisplay ) def startTimer(self): # 设置计时间隔并启动 self.timer.start(1000) #时间为 1 s self.startBtn.setEnabled(False) self.endBtn.setEnabled(True) def endTimer(self): self.timer.stop() self.startBtn.setEnabled(True) #依次循环 self.endBtn.setEnabled(False) if __name__ == "__main__": app = QApplication(sys.argv) form = WinForm() form.show() # QTimer.singleShot(5000, app.quit) #界面运行5秒后,自动关闭 sys.exit(app.exec_()) timerTest()

Módulo QThread, use este módulo para iniciar un hilo, puede crear una subclase de él y luego anular el método QThread.run (). Al llamar a un subproceso personalizado, al llamar al método start () se llamará automáticamente al método de ejecución.
QThread también tiene señales de inicio y finalización. Puede ver que la señal está conectada a la función de ranura

def threadTest():
    class MainWidget(QWidget): def __init__(self,parent=None): super(MainWidget,self).__init__(parent) self.setWindowTitle("QThread 例子") self.thread = Worker() #创建线程 self.listFile = QListWidget() self.btnStart = QPushButton('开始') self.btnStop = QPushButton('结束') layout = QGridLayout(self) layout.addWidget(self.listFile,0,0,1,2) layout.addWidget(self.btnStart,1,1) layout.addWidget(self.btnStop,2,1) self.btnStart.clicked.connect( self.slotStart ) #通过按钮状态实现 线程的开启 self.btnStop.clicked.connect(self.slotStop) self.thread.sinOut.connect(self.slotAdd) def slotStop(self): self.btnStart.setEnabled(True) self.thread.wait(2000) def slotAdd(self,file_inf): self.listFile.addItem(file_inf) #增加子项 def slotStart(self): self.btnStart.setEnabled(False) self.thread.start() #线程开始 #创建一个线程 class Worker(QThread): sinOut = pyqtSignal(str) #自定义一个信号 def __init__(self, parent=None): super(Worker, self).__init__(parent) self.work = True self.num = 0 def run(self): while self.work == True: listStr = 'this is index file {0}'.format(self.num) self.sinOut.emit(listStr) #发射一个信号 self.num += 1 self.sleep(2) #休眠2 秒 def __del__(self): self.work = False self.wait() if __name__ == "__main__": app = QApplication(sys.argv) demo = MainWidget() demo.show() sys.exit(app.exec_()) # threadTest()

demo 2 :

def threadTest2():
    global sec sec=0 class WorkThread(QThread): #自定义一个线程 trigger = pyqtSignal() def __int__(self): super(WorkThread,self).__init__() def run(self): for i in range(2000000000): print('haha ' + str(i)) #此处放运行 量较大的程序 # 循环完毕后发出信号 self.trigger.emit() def countTime(): global sec sec += 1 # LED显示数字+1 lcdNumber.display(sec) def work(): # 计时器每秒计数 timer.start(1000) #每秒运行完后,是lcd增加数字 # 计时开始 workThread.start() # 当获得循环完毕的信号时,停止计数 workThread.trigger.connect(timeStop) def timeStop(): timer.stop() print("运行结束用时",lcdNumber.value()) global sec sec=0 if __name__ == "__main__": app = QApplication(sys.argv) top = QWidget() top.resize(300,120) # 垂直布局类QVBoxLayout layout = QVBoxLayout(top) # 加个显示屏 lcdNumber = QLCDNumber() layout.addWidget(lcdNumber) button = QPushButton("测试") layout.addWidget(button) timer = QTimer() workThread = WorkThread() button.clicked.connect(work) # 每次计时结束,触发 countTime timer.timeout.connect(countTime) top.show() sys.exit(app.exec_()) threadTest2()

 

 

 

Referencia:

Multiproceso https://www.cnblogs.com/kaituorensheng/p/4445418.html

Supongo que te gusta

Origin www.cnblogs.com/junge-mike/p/12761353.html
Recomendado
Clasificación