1. ホーム
  2. python

[解決済み] Pythonマルチプロセッシングモジュールの.join()メソッドは一体何をしているのか?

2022-07-04 14:51:29

質問

Pythonの学習について マルチプロセッシング ( PMOTW 記事 を使用した場合、どのような問題が発生するのでしょうか? join() メソッドが何を行っているのかを明確にしたいのです。

には 2008年の古いチュートリアル によると p.join() を呼び出さないと、子プロセスはアイドル状態になって終了せず、手動で殺す必要があるゾンビになると述べています。

from multiprocessing import Process

def say_hello(name='world'):
    print "Hello, %s" % name

p = Process(target=say_hello)
p.start()
p.join()

のプリントアウトを追加しました。 PID と同様に time.sleep をテストしてみたところ、私が見る限りでは、プロセスは勝手に終了しています。

from multiprocessing import Process
import sys
import time

def say_hello(name='world'):
    print "Hello, %s" % name
    print 'Starting:', p.name, p.pid
    sys.stdout.flush()
    print 'Exiting :', p.name, p.pid
    sys.stdout.flush()
    time.sleep(20)

p = Process(target=say_hello)
p.start()
# no p.join()

20秒以内に

936 ttys000    0:00.05 /Library/Frameworks/Python.framework/Versions/2.7/Reso
938 ttys000    0:00.00 /Library/Frameworks/Python.framework/Versions/2.7/Reso
947 ttys001    0:00.13 -bash

20秒後に

947 ttys001    0:00.13 -bash

動作は p.join() をファイルの末尾に追加しても動作は同じです。Python Module of the Week では モジュールの非常に読みやすい説明 ; "プロセスが作業を終えて終了するまで待つには、join()メソッドを使用します." しかし、少なくともOS Xはいずれにせよそうしていたようです。

また、メソッドの名前についても疑問です。メソッド名は .join() メソッドはここで何かを連結しているのでしょうか?プロセスとその終わりを連結しているのでしょうか?それともPythonのネイティブな .join() メソッドと同じ名前なのでしょうか?

どのように解決するのですか?

この join() メソッドと一緒に使用すると threading または multiprocessing とは関係ありません。 str.join() - とは無関係で、実際に何かを連結しているわけではありません。むしろ、これは単に "この [スレッド/プロセス] が完了するのを待つ" を意味します。名前 join が使われているのは multiprocessing モジュールの API が threading モジュールの API と似ていて threading モジュールは join は、その Thread オブジェクトに変換します。という言葉を使うことで join という言葉を使うことは、多くのプログラミング言語で一般的なので、Pythonもそれを採用したのです。

さて、20秒の遅延が発生するのは、このように join() は、デフォルトではメインプロセスが終了するとき、暗黙のうちに join() を暗黙のうちに呼び出すからです。 multiprocessing.Process インスタンスに適用されます。これは multiprocessing ドキュメントではそれほど明確には述べられていませんが、このことは プログラミング・ガイドライン セクションに記載されています。

<ブロッククオート

また、大文字でないプロセスは自動的に 参加します。

この挙動をオーバーライドするには daemon フラグを Process から True に変更する必要があります。

p = Process(target=say_hello)
p.daemon = True
p.start()
# Both parent and child will exit here, since the main process has completed.

そうすると、子プロセスの はメインプロセスが終了すると同時に終了します :

デーモン

プロセスのデーモンフラグ(ブール値)。これは start() が呼ばれる前に設定されていなければなりません。

初期値は作成プロセスから継承されます。

プロセスが終了するとき、そのデーモンであるすべての 子プロセスを終了させようとします。