Пинтовый модуль python реализует физические величины. Я хотел бы использовать его вместе с многопроцессорной обработкой. Однако я не знаю, как обращаться с созданием UnitRegistry в новом процессе. Если я интуитивное:Пинтовый модуль Python с многопроцессорной обработкой
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()
Затем я получаю следующее исключение:
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'
который я предполагаю, берет свое начало из-за отсутствия инициализации UnitRegistry на дочернем процессе, прежде чем unpickling аргументы. (Инициализация UnitRegistry в функции f не работает, поскольку переменные уже были незакрашены).
Как я могу отправить пинту Количество для дочернего процесса?
Редактировать после ответа Тима Петра:
Проблема заключается в том не привязан к многопроцессорной. Просто засолки количества
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)
и затем unpickling в нового сценария приводит к той же проблеме:
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)
приводит к тем же исключением. Как указывает Тим, достаточно добавить строку Q(50, 'ns'); Q(50, 'ms')
перед рассыпанием. При перекодировании в исходный код для пинты, после создания количества с единицей ms
это устройство добавляется во внутренний реестр. Травление использует экземпляр 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:
Я открыл проблему на сайте github pint.
Bravo! Все это имеет большой смысл. Я только удивлен, что никто не сталкивался с этим раньше - травление в одном процессе и распитие в другом - это использование соленья _usual_ (даже при отсутствии «многопроцессорности»)! –