2016-05-05 19 views
0

これは非常に大きく、SOの質問には大きすぎるので、以下のコードは実際の実装を非常に単純化したデモです。pre-El Capitanマシン上のPython2.7を使用したOS Xのマルチプロセッシングエラー

一般に、イベントスケジューリングに使用する実行時にサブプロセスを起動する、学術的なコンテキスト用の広範なモジュールを作成しました。このモジュールを使用しているスクリプトやプログラムがエルキャピタン以前のマシンで閉じると、子プロセスに参加しようとする私の努力は失敗します。 OS Xは「Pythonが予期せず終了する」というエラーを表示し、孤立したプロセスが継続されます。 私はCSバックグラウンドなしでをマルチプロセッシングするのが大変です。これを診断することは私を超えています。

もし私があまりにも無知であるならば、私はRTFMに行きたいと思っています。具体的な指示は歓迎

私は、この例では、&代表コヒーレントであるかなり確信している、しかし、実際のプロジェクトでは、他のすべての実行時に動作しますが、エルキャピタンに完璧に動作することを知っているが、終了時に説明したように、一貫クラッシュします。私は不合理なタイムアウト値(30秒+)でそれをテストしました。常に同じ結果になります。

最後に、私はこれをPythonのデフォルトのマルチプロセッシングライブラリで開始し、dev友人としてbilliardに切り替えると、よりスムーズに実行できることが示唆されました。今日まで、私は何の違いも経験していません。

UPDATE: @threadedデコレータの目的を与える機能を省略していました。コード内に存在するようになりました。

は一般的に、我々は持っている:

shared_queue = billiard.Queue() # or multiprocessing, have used both 

class MainInstanceParent(object): 
    def __init__(self): 
     # ..typically init stuff.. 
     self.event_ob = EventClass(self) # gets a reference to parent 

    def quit(): 
     try: 
      self.event_ob.send("kkbai") 
      started = time.time() 
      while time.time - started < 1: # or whatever 
       self.event_ob.recieve() 
      if self.event_ob.event_p.is_alive(): 
       raise RuntimeError("Little bugger still kickin'") 
      except RuntimeError: 
       os.kill(self.event_on.event_p.pid, SIGKILL) 

class EventClass(object): 
    def __init__(self, parent): 
     # moar init stuff 
     self.parent = parent 
     self.pipe, child = Pipe() 
     self.event_p = __event_process(child) 

    def receive(): 
     self.pipe.poll() 
     t = self.pipe.recv() 
     if isinstance(t, Exception): 
      raise t 
     return t 

    def send(deets): 
     self.pipe.send(deets) 

def threaded(func): 
    def threaded_func(*args, **kwargs): 
     p = billiard.Process(target=func, args=args, kwargs=kwargs) 
     p.start() 
     return p 
    return threaded_func  

@threaded 
def __event_process(pipe): 
    while True: 
     if pipe.poll(): 
      inc = pipe.recv() 
      # do stuff conditionally on what comes through 
      if inc == "kkbai": 
       return 
      if inc == "meets complex condition to pass here": 
       shared_queue.put("stuff inferred from inc") 
+0

'@ threaded'とは何ですか? 'Queue'を作成する以外は、コードスニペットは' billiard'を使用していないようです。 –

+0

@RolandSmithばかばかしい監視、申し訳ありません。一定。 – Jonline

+0

また、私は 'join'も見ませんか? –

答えて

1

メインプログラムを終了する前に、まだ実行されているどのように多くの子プロセスを確認するためにmultiprocessing.active_children()を呼び出します。これにより、すでに終了しているプロセスもjoinになります。

終了することを子供に知らせる必要がある場合は、子プロセスを開始する前にmultiprocessing.Eventを作成してください。それにはchildren_exitのような意味のある名前を付けてください。子プロセスは、定期的にchildren_exit.is_set()に電話をかけて、終了する必要があるかどうかを確認する必要があります。メインプログラムでは、children_exit.set()を呼び出して子プロセスに信号を送ります。更新

multiprocessingドキュメントのプログラミングのガイドラインてよく見て。

  • それは、これらのガイドラインに述べた理由のためにProcess初期化子のtargetに引数として上記のEventオブジェクトを提供するのが最善です。

  • ms-windowsでコードを実行する必要がある場合は、OSがfork()を実行しないため、余分なフープを飛ばしなければなりません。

アップデート2:あなたのPyEval_SaveThreadエラーの

。完全なトレースを表示するためにあなたの質問を変更することができますか、あるいは別の場所に投稿することができますか? multiprocessingはスレッドを内部的に使用しているため、おそらくスレッドをどこかで使用している場合を除き、これはおそらく原因です。

また、スレッドを使用する場合は、一般的なGUIツールキットであり、特にtkinterはではなく、スレッドセーフであることに注意してください。したがって、Tkinterコールは、のみを1つのスレッドから作成する必要があります。

コードをPython 3に移植するにはどのくらいの労力が必要ですか? Python 2.7のバグであれば、現在のPython 3.5.1ですでに修正されている可能性があります。

+0

これを実装して少し読んだところ、これが私がしなければならないことであることに同意しました。残念ながらコードの振る舞いに変化は見られません。出口トレースは '致命的なPythonエラー:PyEval_SaveThread:NULL tstate'を提供します。このためのGoogleの検索では、両方の 'tkinter'と' numpy'ライブラリの両方のバグが明らかになります。どちらも私の実際の開発環境で使用されています。ここにあるアイデアは、これらの図書館が実際に関与している可能性がありますか?トラブルシューティングの方法 – Jonline

+0

更新された回答を参照してください。 –

+0

とても役に立ちます! Python 3への移植は、残念ながら努力の問題ではなく、コンテキストの1つです。 2.7は、このモジュールの本拠地となるでしょう。 Tkinterは、確かにメインスレッド上でのみ使用されています。まもなく終了エラーの完全なトレースを追加します。 – Jonline

関連する問題