2016-07-18 5 views
0

__init__()メソッドでmultiprocessing.Processサブクラスの状態を初期化することはできますか?それとも、プロセスフォーク時にリソースの重複が発生しますか?私は、コードに注意として、私は__init__方法でセットアップの束をすればPythonマルチプロセッシングサブクラスの初期化

from multiprocessing import Process, Pipe 
import time 

class MyProcess(Process): 
    def __init__(self, conn, bar): 
     super().__init__() 
     self.conn = conn 
     self.bar = bar 
     self.databuffer = [] 

    def foo(self, baz): 
     return self.bar * baz 

    def run(self): 
     '''Process mainloop''' 
     running = True 
     i = 0 
     while running: 
      self.databuffer.append(self.foo(i)) 
      if self.conn.poll(): 
       m = self.conn.recv() 
       if m=='get': 
        self.conn.send((i, self.databuffer)) 
       elif m=='stop': 
        running = False 
      i += 1 
      time.sleep(0.1) 


if __name__=='__main__': 
    conn, child_conn = Pipe() 
    p = MyProcess(child_conn, 5) 
    p.start()  
    time.sleep(2) 

    # Touching the instance does not affect the process which has forked. 
    p.bar=1 
    print(p.databuffer) 

    time.sleep(2) 
    conn.send('get') 
    i,data = conn.recv() 
    print(i,data) 
    conn.send('stop') 
    p.join() 

は、あなたがそのようなファイルハンドルを作成するようにのみPipeを経由して、インスタンスp介してプロセスと通信することはできません。この例を見てみましょうプロセスがフォークすると、これはどのように複製されますか?

これは、multiprocessing.Processをサブクラス化することと同じ方法で、threading.Threadは悪い考えですか?

私のプロセスは長時間実行されており、ブロックIOを処理することに注意してください。

答えて

1

これは簡単にテストできます。 __init__で、次の行を追加します。

self.file = open('does_it_open.txt'.format(self.count), 'w') 

次に実行します。

$ strace -f python youprogram.py 2> test.log 
$ grep does_it_open test.log 
open("does_it_open.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 6 

をあなたのコードをコピーし、その呼び出しを追加し、少なくとも私のシステムであることを意味し、ファイルを一度開かれ、一度だけして。

straceの詳細については、this fantastic blog postを参照してください。

+0

私は 'strace'はメインプロセスだけを見ていると思います。 'open()'メソッドを 'run()'メソッドに移動すると 'strace'に表示されません。 – Mike

+0

良いキャッチ。 '-f'フラグを[forkされたプロセスを含める]に追加してください(http://stackoverflow.com/a/6314744/344286)。 –

+0

'os.getpid()'をファイル名に追加すると、そのファイルが一度だけ開かれることが確認されます。これは、ファイルハンドルを問題なく新しいプロセスに渡すことができるので理にかなっています。私はプロセスが何らかのメモリを共有しているとは思わないので、コンストラクタで重複して割り当てるメモリはありますか? – Mike