POSIX では、Queue
オブジェクトは単純な継承によって子プロセスに共有されます。*
Windows では、これは不可能なので、 をピクルしQueue
、パイプを介して子に送信し、ピクルを解除する必要があります。
(実際に a をピクルしようとするとQueue
、例外が発生するため、これは明らかではないかもしれませんRuntimeError: MyQueue objects should only be shared between processes through inheritance
。ソースを調べると、これが本当に嘘であることがわかります。ピクルしようとすると、この例外が発生するだけです。 a Queue
whenmultiprocess
が子プロセスの生成中でない場合。)
もちろん、2 つのプロセスで同じキューではなく、2 つの同一のキューになってしまうため、一般的な酸洗と酸洗解除は何の役にも立たないでしょう。そのため、 unpickle 時にオブジェクトが使用するメカニズムをmultiprocessing
追加することで、物事を少し拡張します。**のソースを見ると、それがどのように機能するかがわかります。register_after_fork
Queue
しかし、それをフックする方法を知る必要はありません。他のクラスの酸洗と同じ方法でフックできます。たとえば、これはうまくいくはずです:***
def __getstate__(self):
return self.name, super(MyQueue, self).__getstate__()
def __setstate__(self, state):
self.name, state = state
super(MyQueue, self).__setstate__(state)
詳細については、pickle
ドキュメンテーションで、クラスの pickle 化方法に影響を与えるさまざまな方法について説明しています。
(それが機能せず、私がばかげた間違いを犯していない場合...それをフックする方法について少なくとも少しは知っておく必要があります...しかし、ほとんどの場合、事前に追加の作業を行うかどうかを判断するだけですまたは の後、_after_fork()
最後の 2 行を交換するだけで済みます…)
* POSIX プラットフォームで単純な fork 継承を使用することが実際に保証されているかどうかはわかりません。これは 2.7 と 3.3 にも当てはまります。しかしmultiprocessing
、一貫性のためにすべてのプラットフォームで Windows スタイルの pickle-everything を使用するフォークと、OS X でハイブリッドを使用CoreFoundation
してシングル スレッド モードなどで使用できるフォークがあり、その方法で明らかに実行可能です。 .
** 実際には、便宜上のみを使用していると思います 。それがなくても書き直すことができます... しかし、それは Windows またはPOSIXで実行される魔法に依存しています。Queue
register_after_fork
Pipe
_after_fork
Lock
BoundedSemaphore
*** ソースを読んでたまたまそれQueue
が新しいスタイルのクラスであり、__reduce__
or__reduce_ex
をオーバーライドせず、 から誤った値を返すことは決してないため、これは正しいだけ__getstate__
です。それを知らなかったら、もっとコードを書かなければならないでしょう。