この記事では、Python マルチプロセス プログラミング テクノロジを例の形式で分析します。これは、Python プログラミング スキルをさらに高めるのに役立ちます。皆さんの参考に共有してください。具体的な分析は次のとおりです。
一般的に言えば、マルチスレッドではマルチコア CPU を完全に活用できないなど、Python のスレッドにはいくつかの制限があるため、Python ではマルチプロセスを使用することを好みます。ただし、ノンブロッキングの非同期 UI やその他のシナリオを実行する場合は、マルチスレッドも使用します。この記事では主に Python のマルチプロセスの問題について説明します。
Python は 2.6 でマルチプロセス メカニズムを導入し、同時アプリケーションの作成を容易にする豊富なコンポーネントと API を提供しました。 Process、Queue、Pipe、Lock などのマルチプロセッシング パッケージのコンポーネントは、マルチスレッドと同様の機能を提供します。これらのコンポーネントを使用すると、複数プロセスの並行プログラムを簡単に作成できます。
プロセス
Process の使用法は java.lang.Thread に少し似ていますが、Thread はスレッドです。 start メソッドはプロセスを開始するために使用されます。簡単な例:
from multiprocessing import Process import os import time def sleeper(name, seconds): print "Process ID# %s" % (os.getpid()) print "Parent Process ID# %s" % (os.getppid()) print "%s will sleep for %s seconds" % (name, seconds) time.sleep(seconds) if __name__ == "__main__": child_proc = Process(target=sleeper, args=('bob', 5)) child_proc.start() print "in parent process after child process start" print "parent process abount to join child process" child_proc.join() print "in parent process after child process join" print "the parent's parent process: %s" % (os.getppid())
プロセスをインスタンス化するには、ターゲットと引数を指定する必要があります。 target は新しいプロセスのエントリ メソッドであり、メイン メソッドと見なすことができます。 args はメソッドのパラメータリストです。プロセスの開始はスレッドの開始と似ており、start メソッドを呼び出す必要があります。 Process を継承したり、run メソッドをオーバーライドしたり、run メソッドにプロセスのロジックを実装したりすることもできます。 join メソッドを呼び出すと、呼び出されたプロセスが終了するまで、現在の呼び出しプロセスがブロックされます。
プロセスを手動で終了するには、terminate メソッドを呼び出します。UNIX システムでは、このメソッドは SIGTERM セマフォを送信し、Windows システムでは、TerminateProcess メソッドを使用します。終了処理ロジックは実行されず、このプロセスの子プロセスは終了せず、孤立プロセスになるだけであることに注意してください。
キュー
Queue はマルチプロセス安全なキューです。Queue を使用して複数のプロセス間でデータを転送できます。 put メソッドは、キューにデータを挿入するために使用されます。put メソッドには、blocked と timeout という 2 つのオプションのパラメータもあります。 Blocked が True (デフォルト値) で、timeout が正の値の場合、このメソッドは、キューにスペースが残るまで、timeout で指定された時間ブロックします。タイムアウトになると、Queue.Full 例外がスローされます。ブロックが False であってもキューがいっぱいの場合、Queue.Full 例外がすぐにスローされます。
get メソッドは、キューから要素を読み取り、削除できます。同様に、get メソッドには、blocked と timeout という 2 つのオプションのパラメータがあります。 Blocked が True (デフォルト値) で、timeout が正の値の場合、待機時間中に要素がフェッチされないと、Queue.Empty 例外がスローされます。 Blocked が False の場合、キューに使用可能な値がある場合はその値がすぐに返され、キューが空の場合はすぐに Queue.Empty 例外がスローされます。 Queueのサンプルコード:
from multiprocessing import Process, Queue def offer(queue): queue.put("Hello World") def test(queue, num): queue.put("Hello World: " + str(num)) if __name__ == '__main__': q = Queue() p1 = Process(target=test, args=(q, 1)) p1.start() p = Process(target=offer, args=(q,)) p.start() p2 = Process(target=test, args=(q, 2)) p2.start() p2 = Process(target=test, args=(q, 3)) p2.start() print q.get() print q.get() print q.get() print q.get() print q.close()
出力:
Hello World: 1
ハローワールド
ハローワールド: 2
なし
パイプ
Pipe メソッドは、パイプの両端を表す (conn1, conn2) を返します。 Pipe メソッドには duplex パラメーターがあり、duplex パラメーターが True (デフォルト値) の場合、パイプは全二重モードになり、conn1 と conn2 の両方が送受信できることになります。 duplex は False で、conn1 はメッセージの受信のみを担当し、conn2 はメッセージの送信のみを担当します。
sendメソッドとrecvメソッドは、それぞれメッセージを送信および受信するためのメソッドです。たとえば、全二重モードでは、conn1.send を呼び出してメッセージを送信し、conn1.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()
同期
マルチプロセッシング パッケージは、条件、イベント、ロック、RLock、セマフォ、および同期用のその他のコンポーネントを提供します。以下はロックの使用例です:
from multiprocessing import Process, Lock def l(lock, num): lock.acquire() print "Hello Num: %s" % (num) lock.release() if __name__ == '__main__': lock = Lock() for num in range(20): Process(target=l, args=(lock, num)).start()
概要
上記は、Python マルチプロセッシング ライブラリの簡単な紹介と例です。Java マルチスレッド開発に慣れている学生にとっては、これは Java の同時実行 API に非常によく似ていますが、javaConcurrency はマルチスレッドのみを処理します。これらの API を使用して、以前の Java マルチスレッド エクスペリエンスを直接追跡できます。
興味のある友人は、この記事の例をテストして実行し、理解を深めることができます。この記事で説明されている内容は、皆さんが Python プログラミングを学習する上で一定の参考価値があると信じています。