Pythonプロセス


Pythonは2.6でマルチプロセスのメカニズムを導入し、豊富なコンポーネントとapiを提供し、同時アプリケーションの作成を容易にした.MultiprocessingパッケージのコンポーネントProcess,Queue,Pipe,Lockなどのコンポーネントはマルチスレッドと同様の機能を提供する.これらのコンポーネントを使用すると、マルチプロセスコンカレントプログラムを簡単に作成できます.
マルチプロセスインスタンス:
import os
from multiprocessing import Process

def info(title):
   print(title)
   print('module name:', __name__)
   print('parent process:', os.getppid())
   print('process id:', os.getpid())
   print("

")

def f(name):
   info('\033[31;1mfunction f\033[0m')
   print('hello', name)

if __name__ == '__main__':
   info('\033[32;1mmain process line\033[0m')
   p = Process(target=info, args=('bob',))
   p.start()
   p.join()

プロセスをインスタンス化するにはtargetとargsを指定する必要があります.targetは新しいプロセスのエントリメソッドでありmainメソッドと考えられる.argsはこの方法のパラメータリストです.起動プロセスはThreadを起動するのと同じで、startメソッドを呼び出す必要があります.プロセスを継承し、runメソッドを上書きし、runメソッドでプロセスの論理を実現することもできます.joinメソッドを呼び出すと、呼び出されたプロセスの実行が終了するまで、現在の呼び出しプロセスがブロックされます.
プロセスを手動で終了するとterminateメソッドが呼び出され、UNIXシステムではSIGTERM信号量が送信され、windowsシステムではTerminateProcessメソッドが使用されます.注意すべきは、exit処理ロジックは実行されず、プロセスのサブプロセスは終了されず、孤児プロセスになるだけである.
プロセス間通信
Queue
Queueはマルチプロセスの安全なキューであり,Queueを用いてマルチプロセス間のデータ転送を実現できる.putメソッドはキューにデータを挿入するために使用され、putメソッドにはblockedとtimeoutの2つのオプションパラメータがあります.blockedがTrue(デフォルト)であり、timeoutが正の場合、このメソッドは、キューに残りのスペースがあるまでtimeoutが指定した時間をブロックします.タイムアウトするとQueueが投げ出されます.Full異常.blockedがFalseであるが、Queueが満タンであると、すぐにQueueが投げ出される.Full異常.
getメソッドは、キューから要素を読み出して削除できます.同様にgetメソッドには、blockedとtimeoutの2つのオプションパラメータがあります.blockedがTrue(デフォルト)、timeoutが正の場合、待ち時間内に要素が取り込まれず、Queueが放出する.Empty異常.blockedがFalseである場合には2つのケースがあり、Queueに1つの値が利用可能である場合は直ちにその値を返す、そうでない場合はキューが空である場合は直ちにQueueを投げ出す.Empty異常.Queueのサンプルコード:
from multiprocessing import Process, Queue

def f(q):
   q.put([42, None, 'hello'])

if __name__ == '__main__':
   q = Queue()
   p = Process(target=f, args=(q,))
   p2 = Process(target=f, args=(q,))
   p.start()
   p2.start()
   print('data1:',q.get())    # prints "[42, None, 'hello']"
   
print('data2:',q.get())
   p.join()

Pipes
Pipeメソッドは、1つのパイプの2つの端を表す(conn 1,conn 2)を返します.Pipeメソッドにはduplexパラメータがあり、duplexパラメータがTrue(デフォルト)の場合、このパイプはフルデュプレクスモード、すなわちconn 1とconn 2が送受信可能である.duplexはFalseであり,conn 1はメッセージの受信のみを担当し,conn 2はメッセージの送信のみを担当する.
sendメソッドとrecvメソッドは、それぞれメッセージを送信および受信する方法である.例えば、conn 1は、フルデュプレクスモードで呼び出すことができる.send送信メッセージconn 1.recvメッセージを受信します.メッセージが受信できない場合、recvメソッドはブロックされます.パイプが閉じられている場合、recvメソッドはEOFErrorを放出します.
from multiprocessing import Process, Pipe

def send(conn):
   conn.send("Hello World")
   conn.close()

if __name__ == '__main__':
   parent_conn, child_conn = Pipe()
   p = Process(target=send, args=(child_conn,))
   p.start()
   print(parent_conn.recv())

Managers
from multiprocessing import Process, Manager

def f(d, l):
   d[1] = '1'
   
d['2'] = 2
   
d[0.25] = None
   
l.append('a')
   print(l)

if __name__ == '__main__':
   with Manager() as manager:
       d = manager.dict()
       l = manager.list(range(5))
       p_list = []
       for i in range(10):
           p = Process(target=f, args=(d, l))
           p.start()
           p_list.append(p)
       for res in p_list:
           res.join()

       print(d)
       print(l)

プロセス同期
Multiprocessingパッケージには、Condition、Event、Lock、RLock、Semaphoreなどのコンポーネントが同期に使用できます.ロックを使用する例を次に示します.
from multiprocessing import Process, Lock

def f(l, i):
   l.acquire()
   try:
       print('hello world', i)
   finally:
       l.release()

if __name__ == '__main__':
   lock = Lock()

   for num in range(10):
       Process(target=f, args=(lock, num)).start()

プロセスプール
プロセスプール内でプロセスシーケンスを維持し、使用するとプロセスプールにプロセスを取得します.プロセスプールシーケンスに使用可能なプロセスがない場合、プロセスプールに使用可能なプロセスがあるまでプログラムは待機します.
プロセスプールには、次の2つの方法があります.
  • apply
  • apply_async
  • from  multiprocessing import Process,Pool,freeze_support
    import time

    def Foo(i):
       time.sleep(2)
       return i+100

    def Bar(arg):
       print('-->exec done:',arg)


    if __name__ == '__main__':
           freeze_support()
           pool = Pool(3)  
           for i in range(10):
               pool.apply_async(func=Foo, args=(i,),callback=Bar)  #
               #pool.apply(func=Foo, args=(i,))    #

           
    print('end')
           pool.close()
           pool.join()  # , , 。