Python例外メカニズム、マルチプロセス、PyQt5のQTimer、マルチスレッド

1.例外処理メカニズム

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.マルチプロセス

マルチプロセスライブラリファイルの紹介:マルチプロセッシングのインポート 

マルチプロセステストの場合、メイン関数mainでテストして
 プロセスクラス作成する必要があります。Process([group [、target [、name [、args [、kwargs]]]]]])、targetは呼び出しオブジェクトを表し、argsは呼び出しオブジェクトを表します位置パラメータのタプル。kwargsは、呼び出し元オブジェクトの辞書を表します。nameはエイリアスです。グループは基本的に使用されません。
 メソッド:is_alive()、join([timeout])、run()、start()、terminate()。その中で、Processはstart()でプロセスを開始します。
 属性:authkey、デーモン(start()で設定)、exitcode(プロセスが実行時にNoneであり、それが–Nの場合、シグナルNで終了することを意味します)、名前、pid。デーモンは親プロセスが終了すると自動的に終了し、それ自体では新しいプロセスを作成できません。開始前に設定する必要があります()

デーモンはデーモンプロセスです。デーモンは親プロセスの終了後に自動的に終了し、それ自体では新しいプロセスを作成できません。開始前に設定する必要があります()。#メインスレッドの実行が完了すると、子スレッドの実行が完了したかどうかに関係なく、メインスレッドで終了します。

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----')

出力:

#---没有 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----  

複数のプロセスを使用して共有リソースにアクセスする場合は、アクセスの競合を回避するためにロックを使用する必要があります

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()

出力:

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

プロセスプール

プロセスプール
 がシステム管理にPythonを使用する場合  、特に複数のファイルディレクトリを同時に操作する場合、または複数のホストをリモート制御する場合、並列操作により多くの時間を節約できます。操作するオブジェクトの数が多くない場合、マルチプロセッシングでプロセスを直接使用して、1ダース程度の複数のプロセスを動的に生成できますが、数百または数千のターゲットの場合、手動でプロセスの数を制限するには多すぎます面倒すぎる場合は
 、この時点でプロセスプールの役割を果たすことができます。プールは、ユーザーが呼び出すための指定された数のプロセスを提供できます。プールに新しいリクエストが送信されると、プールがいっぱいでない場合、リクエストを実行するための新しいプロセスが作成されますが、プール内のプロセスの数が指定された最大値に達した
 場合、要求はプール内のプロセスが終了するまで待機し、新しいプロセスを作成しません。
 
apply_async(func [、args [、kwds [、callback]]])これは非ブロッキングで、apply(func [、args [、kwds]])はブロッキングです

非ブロッキングおよびブロッキングプロセスプール

単一の関数がスレッドプールを使用します。

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]) #获取结果

出力:

#---非阻塞进程池 输出------
# 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

複数の機能のスレッドプール

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------')

get()関数を使用して、パンダのデータ構造を取得することもできます。

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())

 出力結果:

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. PyQt5のQTimerモジュール

pyqt5でのマルチスレッドの適用、マルチスレッドテクノロジーには、3つの方法が含まれます。1。タイマーQTimerを使用します。2。マルチスレッドモジュールQThreadを
使用します。3。イベント処理関数を使用します。1。QTimerモジュールを使用し、QTimerインスタンスを作成し、タイムアウト信号を作成しますスロット関数に接続し、タイムアウト信号を呼び出します。self.timer.start(1000)時間がPyQt5.QtCoreからミリ秒単位で
導入されます
。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()

QThreadモジュール。このモジュールを使用してスレッドを開始し、そのサブクラスを作成して、QThread.run()メソッドをオーバーライドできます。カスタムスレッドを呼び出すときに、start()メソッドを呼び出すと、自動的にrunメソッドが呼び出されます
。QThreadもシグナルを開始および終了しました。シグナルがスロット関数に接続されていることがわかります

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()

デモ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()

 

 

 

参照:

マルチプロセスhttps://www.cnblogs.com/kaituorensheng/p/4445418.html

おすすめ

転載: www.cnblogs.com/junge-mike/p/12761353.html