2016-07-17 26 views
2

python pintモジュールは物理量を実装します。マルチプロセッシングと一緒に使用したいと思います。しかし、新しいプロセスでUnitRegistryを作成する方法を知りません。私は直感的な操作を行う場合:私は、引数をunpickle化する前に子プロセスにUnitRegistryの初期化の欠如に由来すると仮定マルチプロセッシングを使用したPython pintモジュール

Traceback (most recent call last): 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\multiprocessing\process.py", line 254, in _bootstrap 
    self.run() 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\multiprocessing\process.py", line 93, in run 
    self._target(*self._args, **self._kwargs) 
File "C:\Users\pmaunz\PyCharmProjects\IonControl34\tests\pintmultiprocessing.py", line 12, in f 
    print(one/two) 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\site-packages\pint\quantity.py", line 738, in __truediv__ 
    return self._mul_div(other, operator.truediv) 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\site-packages\pint\quantity.py", line 675, in _mul_div 
    offset_units_self = self._get_non_multiplicative_units() 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\site-packages\pint\quantity.py", line 1312, in _get_non_multiplicative_units 
    offset_units = [unit for unit in self._units.keys() 
File "C:\WinPython-64bit-3.4.4.2Qt5\python-3.4.4.amd64\lib\site-packages\pint\quantity.py", line 1313, in <listcomp> 
    if not self._REGISTRY._units[unit].is_multiplicative] 
KeyError: 'millisecond' 

from multiprocessing import Process 
from pint import UnitRegistry, set_application_registry 

ureg = UnitRegistry() 
set_application_registry(ureg) 
Q = ureg.Quantity 


def f(one, two): 
    print(one/two) 

if __name__ == '__main__': 
    p = Process(target=f, args=(Q(50, 'ms'), Q(50, 'ns'))) 
    p.start() 
    p.join() 

は、それから私は、次の例外を取得します。 (関数fのUnitRegistryの初期化は、変数が既にunpickleされているので機能しません)。

子プロセスにQuantityを送信するにはどうすればいいですか?ティムピーターの答えの後

編集:

問題はマルチプロセッシングに縛らないです。同じ例外で

from pint import UnitRegistry, set_application_registry 
import pickle 
ureg = UnitRegistry() 
set_application_registry(ureg) 
Q = ureg.Quantity 
with open("pint.pkl", 'rb') as f: 
    t1 = pickle.load(f) 
    t2 = pickle.load(f) 

print(t1/t2) 

結果:単に新しいスクリプトにunpickle化すると、同じ問題につながり、その後

from pint import UnitRegistry, set_application_registry 
import pickle 
ureg = UnitRegistry() 
set_application_registry(ureg) 
Q = ureg.Quantity 
with open("pint.pkl", 'wb') as f: 
    pickle.dump(Q(50, 'ms'), f) 
    pickle.dump(Q(50, 'ns'), f) 

量を酸洗して。 Timが指摘しているように、アンピクルの前にQ(50, 'ns'); Q(50, 'ms')行を追加すれば十分です。パイントのソースコードを掘り下げると、ユニットmsで数量を作成すると、このユニットは内部レジストリに追加されます。 picklingはUnitContainerインスタンスを使用してユニットを保存します。番号を付けないで数量を作成すると、がレジストリに追加されます。

(パイントソースコードで)単純な修正は、文字列を返すように機能Quantity.__reduce__を変更することです。

diff --git a/pint/quantity.py b/pint/quantity.py 
index 3f30a25..695866a 100644 
--- a/pint/quantity.py 
+++ b/pint/quantity.py 
@@ -57,7 +57,7 @@ class _Quantity(SharedRegistryObject): 

    def __reduce__(self): 
     from . import _build_quantity 
-  return _build_quantity, (self.magnitude, self._units) 
+  return _build_quantity, (self.magnitude, str(self._units)) 

    def __new__(cls, value, units=None): 
     if units is None: 

私はpintのgithubサイトで問題をオープンしました。

+0

ブラボー!それはすべて理にかなっています。私は驚くことに、誰もこれにぶつかりませんでした。一つのプロセスで漬け込み、別のプロセスではunpickleは、(マルチプロセッシングがない場合でも)漬け物が使われています! –

答えて

1

は私が前にpintを使ったことがないが、これは私が指摘面白い;-)最初のものを見て、私は明示的にこの行で記載されているユニットに固執する場合、私は何の問題もないということです。たとえば

print(dir(ureg.sys.mks)) 

、「時間」および 『第2』というの出力の両方であり、そしてProcessラインに変更された場合、プログラムは正常に実行されますので、multiprocessingが使用している、あなたがWindows上だ

p = Process(target=f, args=(Q(50, 'hour'), Q(50, 'second'))) 

『卵』の方法を:全体のプログラムは、作業者プロセス、特に:

ureg = UnitRegistry() 
set_application_registry(ureg) 
Q = ureg.Quantity 

行もワーカープロセスで実行されました。したがって、ユニットレジストリはワーカーで初期化されたですが、メインプログラムで使用されているレジストリと同じではありません。つまり、プロセス間でメモリは共有されません。より深い取得するには

私たちは本当にpintの実装方法の専門家を必要としています。私の推測では、文字列を解析することによってユニットが "作られた"(上記のdir()によって生成された出力ではない)、後で値を再構成するために必要な新しいレベルがレジストリに追加されます。 「ns」と「ms」はこの性質のもので、出力ではではなく、です。

-であるように私はすぐにあなたのQ=ureg.Quantity行の後にこのような行を追加します場合、プログラムが正常に動作します:

Q(1, 'ms'); Q(1, 'ns') 

働いた暗闇の中でショット(「推測」)でした:それは、作業プロセスが、メインプロセスで使用された同じ「構成された」ユニットを解析して、ユニットレジストリを同様の状態に強制しようとしました。

もっとクリーンな方法で作業することを望みますが、それ以上のことはできません。私はそれについてpintの著者に尋ねるでしょう。

関連する問題