2017-06-22 14 views
2

最後の目標は、バックグラウンドでメソッドを実行することですが、並列ではありません:複数のオブジェクトがこのメソッドを呼び出すときは、バックグラウンドでの実行を実現するには、サブプロセス(スレッドではない)でメソッドを実行しなければならず、spawn(forkではなく)を使用してメソッドを開始する必要があります。並列実行を防ぐために、明らかな解決策は、プロセス間で共有されるグローバルロックを設けることです。
次のコードの両方で強調表示されているように、Unixのデフォルトであるプロセスがforkされると、簡単に達成できます。
私たちは、クラス変数としてそれを共有することができますPython:生成されたプロセス間でロックを共有すること

import multiprocessing as mp 
from time import sleep 

class OneAtATime: 

    l = mp.Lock() 

    def f(self): 
     with self.l: 
      sleep(1) 
     print("Hello") 

if __name__ == "__main__": 
    a = OneAtATime() 
    b = OneAtATime() 
    p1 = mp.Process(target = a.f) 
    p2 = mp.Process(target = b.f) 
    p1.start() 
    p2.start() 

それともメソッドに渡すことができます:

import multiprocessing as mp 
from time import sleep 

class OneAtATime: 
    def f(self, l): 
     with l: 
      sleep(1) 
     print("Hello") 

if __name__ == "__main__": 
    a = OneAtATime() 
    b = OneAtATime() 
    m = mp.Manager() 
    l = mp.Lock() 
    p1 = mp.Process(target = a.f, args = (l,)) 
    p2 = mp.Process(target = b.f, args = (l,)) 
    p1.start() 
    p2.start() 

これらのコードのいずれもが1秒で「こんにちは」印刷の適切な行動を持っています間隔の。 しかし、start methodを 'スポーン'に変更すると、それらは壊れてしまいます。
最初の(1)は、両方の "hello"を同時に印刷します。これは、the internal state of a class is not pickledなので、同じロックを持たないからです。
2番目のファイル(2)は、実行時にFileNotFoundErrorで失敗します。私はそれがロックが漬けにされないという事実と関係していると思う:Python sharing a lock between processesを参照してください。
この回答では、2つの修正が提案されています(注:私は任意の数のプロセスをランダムに作成したいのでプールを使用できません)。
私は2番目の修正を適応させる方法を発見していないが、私は最初のものを実装してみました:

import multiprocessing as mp 
from time import sleep 

if __name__ == "__main__": 
    mp.set_start_method('spawn') 

class OneAtATime: 
    def f(self, l): 
     with l: 
      sleep(1) 
     print("Hello") 

if __name__ == "__main__": 
    a = OneAtATime() 
    b = OneAtATime() 
    m = mp.Manager() 
    l = m.Lock() 
    p1 = mp.Process(target = a.f, args = (l,)) 
    p2 = mp.Process(target = b.f, args = (l,)) 
    p1.start() 
    p2.start() 

これははAttributeErrorとFileNotFoundError(3)で失敗します。実際には、forkメソッドが使用されているとき(BrokenPipe)も失敗します(4)。
スポーンされたプロセス間でロックを共有する適切な方法は何ですか?
私が番号をつけた4つの失敗の簡単な説明も良いでしょう。 私はArchlinuxでPython 3.6を実行しています。

+0

ドキュメントをかなり慎重に読んだようです。 [17.2.1.5](https://docs.python.org/3.6/library/multiprocessing.html#sharing-state-between-processes)のソリューションを見てきましたか?ロックを共有メモリまたはマネージャーに入れることができるはずですか? –

+0

私は試してみましたが、これは3番目のコードスニペットです。それは動作しませんでしたが、おそらくトリックを行うなど、これを行うための多くの方法があります。 – Zil0

+0

申し訳ありませんが、私はコメントする前にコードをさらに研究していたはずです。 :-) –

答えて

1

スクリプトが途中で終了しない限り、最後のコードスニペットが機能します。プロセスを結合するだけで十分です。

ここで発生したエラーの詳細https://stackoverflow.com/a/25456494/8194503

+0

これについて言及したので、すぐにそのことを考えていたはずです。質問と答えの両方で良い研究。 –

1

おめでとうございます。そこには90%の道があります。最後のステップは、実際に行うのはあまり難しくありません。

はい、最終的なコードブロックはAttributeErrorで失敗しますが、特にエラーは何ですか? "属性 'OneAtATime'を取得できません"。これはすでに遭遇した問題と非常によく似ています。クラスOneAtATimeを漬けていません。

私は、次の変更を加えた、あなたが好きなそれが働いた:

file ooat.py:

from time import sleep 

class OneAtATime: 
    def f(self, l): 
     with l: 
      sleep(1) 
     print("Hello") 

interactive shell:

import multiprocessing as mp 
from oaat import OneAtATime 
if __name__ == "__main__": 
    mp.set_start_method('spawn') 
    a = OneAtATime() 
    b = OneAtATime() 
    m = mp.Manager() 
    l = m.Lock() 
    p1 = mp.Process(target = a.f, args = (l,)) 
    p2 = mp.Process(target = b.f, args = (l,)) 
    p1.start() 
    p2.start() 

をあなたが、私は本当に何もしなかった、気づくこと - ちょうどあなたのコードを分割2つの別々のファイルに分割します。それを試してみると、うまく動作するのが分かります。 (少なくとも私のために、ubuntuでpython 3.5を使っていました)

+0

私はspawnメソッドでテストするのを忘れているのを見て、この回答を一時的に削除しました。それから、私がテストをしたとき、「OneAtATimeは定義されていません」と言っていましたが、 'from ooat import OneAtATime'行を忘れたからです。だから私は明らかにフォークとスポーンの両方をテストして、それは正常に動作します。 –

+0

あなたの投稿に回答はありますが、あなたの投稿にはありません。これは "対話シェル"です。実際、私が得たエラーは次のとおりです。AttributeError: 'ForkAwareLocal'オブジェクトに属性 '接続'がありません。 私は試してみることを中止し、質問を書いたが、私は実際の解決策から離れていた。https://stackoverflow.com/a/25456494/8194503。 これは、私のために同じファイルで完全に正常に動作し、エラーが何であるかは不明です。私は修正で私の質問を編集します。 私はあなたの答えを受け入れる必要がありますどのような礼儀にあるかわからない、私はそれをとにかく受け入れると思います。御時間ありがとうございます ! – Zil0

+1

あなたの問題を解決していない場合は、実際にあなたの答えを投稿し、それが何かを伝えるまで待ち、あなた自身の答えを受け入れるべきです。これは完全に適切なことです。時間が経つにつれて、あなたは答えをアップアップします。 –

関連する問題