2016-10-06 5 views
0

python mutiprocessingを使用して観察された以下の奇妙な動作を理解しようとしています。Pythonマルチプロセッシングでの予期しない動作

サンプルTestClassを:

class testClass(multiprocessing.Process):  

    def __del__(self): 
     print "__del__ PID: %d" % os.getpid() 
     print self.a  

    def __init__(self): 
     multiprocessing.Process.__init__(self) 
     print "__init__ PID: %d" % os.getpid() 
     self.a = 0  

    def run(self): 
     print "method1 PID: %d" % os.getpid() 
     self.a = 1 

そして少しテストプログラムをマルチプロセッシング 輸入OS インポート:

TestClassをインポートTestClassをから
print "Start" 
proc_list = [] 
proc_list.append(testClass()) 
proc_list[-1].start()  

proc_list[-1].join()  

print "End" 

これが生成します。

Start 
__init__ PID: 89578 
method1 PID: 89585 
End 
__del__ PID: 89578 
0 

なぜd oesは印刷されません1

runが実際には異なるプロセスで実行されていることがわかります。これが期待される動作であれば、プロセスを高価な__init__にして、データベースをオープンする必要のあるプロセスと同じようにマルチプロセスを使用する人はどうでしょうか?

マルチプロセッシングのドキュメントでこの動作を強調表示しないでください。

+0

「1」を印刷するコードはどれですか? – zvone

+0

__del__からself.aを印刷します。実行メソッドは1に設定しますが、Python-Multiprocessingではデストラクタに伝播されません。 – Usul

答えて

0

あなたはコンテキストマネージャの内部で、あなたの高価な初期化をラップすることができます:あなたは正しくdo_some_logic_hereを呼び出す前に、あなたのオブジェクトを初期化する機会を持つことになりますし、適切にコンテキストマネージャのブロックを出た後にリソースを解放するために

def run(self): 
    with expensive_initialization() as initialized_object: 
     do_some_logic_here(initialized_object) 

documentationを参照してください。

+0

私は可能でしたが、プロセスに何か悪いことが起きた場合、またはユーザーが期待どおりに実際に使用しなかった場合にデータベースを適切に閉じられるように、__del__にコードを追加したかったので、この「問題」を見ました。他の回避策はありませんか? – Usul

+1

'__del__'を使うと、何か悪いことが起きたときにコードが呼び出されることはありません。それは単なるデコンストラクタです。実際に何か悪いことが起こった場合、クリーンアップコードが実行される可能性もありません。このプロセスクラスをユーザに提供し、それらがコンテキストマネージャを適切に使用しているかどうかを確認するには、サブクラス(doやexecuteなど)でオーバーライドされる別のスタブメソッドを作成し、 'self.do () '内部のコンテキストマネージャ内部で' –

0

start()を呼び出すと、インタプリタは子プロセスを作成して作成します。子プロセスは親からページテーブルのコピーを取得します。これらは、読み取り専用としてマークされ、書き込まれたときにのみコピーされるページを指します(COW)。インタプリタは、子プロセスでrunを実行すると、子どものPyObjectのコピー(aを表す)にアクセスします。親の記憶には触れられていません。子はファイル記述子テーブルのコピーも取得します。つまり、親によって接続が開かれた場合、そのファイル記述子は子によって継承されます。あなたは子供がCLONE_FILESなしcloneを介して作成されていること(straceで)見ることができます:

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f460d8929d0) 

したがって、クローンのmanページから:

CLONE_FILESが設定されていない場合、子プロセスがのコピーを継承しますclone()の時点で呼び出し元のプロセスで開かれたすべてのファイル記述子。 (子プロセス内の重複したファイル記述子は、呼び出し元プロセスの対応するファイル記述子と同じ、開いているファイル記述子(open(2)を参照)を参照します)。ファイル記述子を開いたり閉じたりするファイル記述子フラグを変更する呼び出しプロセスまたは子プロセスのいずれかが他のプロセスに影響を与えません。

関連する問題