如何在 Python 中使用 Managers() 在多个进程之间共享字符串?

Posted

技术标签:

【中文标题】如何在 Python 中使用 Managers() 在多个进程之间共享字符串?【英文标题】:How to share a string amongst multiple processes using Managers() in Python? 【发布时间】:2014-02-12 23:38:24 【问题描述】:

我需要从主进程中读取由 multiprocessing.Process 实例编写的字符串。我已经使用管理器和队列将参数传递给进程,所以使用管理器似乎很明显,but Managers do not support strings:

Manager() 返回的管理器将支持类型列表、字典、 命名空间、锁、RLock、信号量、有界信号量、条件、事件、 队列、值和数组。

如何使用多处理模块中的管理器共享由字符串表示的状态?

【问题讨论】:

【参考方案1】:

multiprocessing 的 Manager 可以保存 Values,而后者又可以保存 ctypes 模块中 c_char_p 类型的实例:

>>> import multiprocessing
>>> import ctypes
>>> v = multiprocessing.Value('c', "Hello, World!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/multiprocessing/__init__.py", line 253, in Value
    return Value(typecode_or_type, *args, **kwds)
  File "/usr/lib/python2.7/multiprocessing/sharedctypes.py", line 99, in Value
    obj = RawValue(typecode_or_type, *args)
  File "/usr/lib/python2.7/multiprocessing/sharedctypes.py", line 73, in RawValue
    obj.__init__(*args)
TypeError: one character string expected
>>> cstring = multiprocessing.Value(ctypes.c_char_p, "Hello, World!")
>>> cstring
<Synchronized wrapper for c_char_p(166841564)>
>>> cstring.value
'Hello, World!'

对于 Python 3, 使用 c_wchar_p 代替 c_char_p

另请参阅:Post with the original solution,我很难找到。

因此,可以使用 Manager 在 Python 中的多个进程下共享字符串,如下所示:

>>> from multiprocessing import Process, Manager, Value
>>> from ctypes import c_char_p
>>> 
>>> def greet(string):
>>>     string.value = string.value + ", World!"
>>> 
>>> if __name__ == '__main__':
>>>     manager = Manager()
>>>     string = manager.Value(c_char_p, "Hello")
>>>     process = Process(target=greet, args=(string,))
>>>     process.start()
>>>     process.join()    
>>>     print string.value
'Hello, World!'

【讨论】:

我想知道为什么会这样(共享指针),并且从消息来源中我了解到managers.Value 实际上根本没有使用typecode 参数。该字符串不会转换为c_char_pmultiprocessing.Value 的工作方式非常不同。 我试过s = multiprocessing.Value(c_char_p, "old string")s.value = "new string" 经常丢失指针。我还尝试了另一种更稳定的Array('c', fixed_length) 解决方案。 如果你试图摆脱Manager,它不会起作用,因为c_wchar_p只是一个指向数据的指针,所以当另一个进程访问它时,它会直接转到@987654336 @。更多解释可以在这里找到:***.com/a/12343115/3300539。是的,正如之前的评论中提到的,Array('c', fixed_length) 也适用于我。【参考方案2】:

只需将字符串放入dict

d = manager.dict()
d['state'] = 'xyz'

由于字符串本身是不可变的,因此直接共享一个不会有用。

【讨论】:

manager.dict() 速度较慢,因为它返回一个代理,并且代理总是将数据从一个线程复制到另一个线程,而multiprocessing.Value() 速度更快,因为它返回一个实际的共享内存区域,该区域只是直接访问的每个进程。

以上是关于如何在 Python 中使用 Managers() 在多个进程之间共享字符串?的主要内容,如果未能解决你的问题,请参考以下文章

Python文摘:Python with Context Managers

python manager.dict()锁定如何工作:

如何在 laravel 中更新时验证电子邮件

Python 分布式进程间通讯

Django--Managers

未找到列:Laravel 5 多对多关系查询中“on 子句”中的 1054 未知列“managers.id”