gpt4 book ai didi

具有多处理功能的 Python pint 模块

转载 作者:太空宇宙 更新时间:2023-11-04 05:26:52 25 4
gpt4 key购买 nike

python pint 模块实现了物理量。我想将它与多处理一起使用。但是,我不知道如何处理在新进程中创建 UnitRegistry。如果我凭直觉:

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。 (在函数 f 中初始化 UnitRegistry 不起作用,因为变量已经被 unpickled)。

我将如何向子进程发送一品脱 Quantity?

根据 Tim Peter 的回答进行编辑:

问题是与多处理有关。简单酸洗数量

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)

导致相同的异常。正如 Tim 指出的那样,添加一行 Q(50, 'ns'); 就足够了。 Q(50, 'ms') 解酸洗之前。在深入研究 pint 的源代码时,在创建单位为 ms 的数量时,该单位被添加到内部注册表中。 Pickling 使用 UnitContainer 实例来保存单位。通过 unpickling 创建数量时,单位不会添加到注册表中。

一个简单的修复(在 pint 源代码中)是更改函数 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 站点上打开了一个问题。

最佳答案

我以前从未使用过 pint,但这看起来很有趣 ;-) 我注意到的第一件事是,如果我坚持使用此行明确列出的单位,我没有问题:

print(dir(ureg.sys.mks))

例如,“hour”和“second”都在输出中,如果 Process 行更改为:

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

你在 Windows 上,所以 multiprocessing 使用“spawn”方法:整个程序由工作进程重新导入,所以特别是:

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

行也在工作进程中执行。因此,单元注册表在工作程序中初始化的,但它与主程序中使用的注册表不同(相同)——进程之间不共享内存。

为了更深入,我们确实需要一位了解如何实现 pint 的专家。我的猜测是,对于通过解析字符串“组成”的单元(不是在上面的 dir() 行生成的输出中),新内容会在某个级别添加到注册表中,稍后需要重建值。 “ns”和“ms”具有这种性质:它们dir() 输出中。

您的程序按原样运行良好如果我在您的Q=ureg.Quantity 行之后立即添加这样一行:

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

那是在黑暗中开枪(“有根据的猜测”):它只是迫使工作进程解析主进程中使用的相同“组成”单元,以试图强制 它的 单元注册表进入类似状态。

我希望有一种更简洁的方法让它工作,但帮不上什么忙。我会询问 pint 作者。

关于具有多处理功能的 Python pint 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38417527/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com