Python 3.x 服务器重新启动时多处理BaseManager的意外行为
我正在构建一个由几个独立进程组成的应用程序,其中每个进程都是一个python程序。它们都由supervisord实用程序启动,并在运行Ubuntu18.04下的Python3.8.0的venv中执行 其思想是进程通过队列进行通信,因此问题是如何将队列发送到进程。我的解决方案是使用多处理管理器来实现队列存储库。每个进程按名称请求队列 由于整个应用程序需要健壮,因此如果队列服务器进程停止并重新启动(由supervisord自动启动),它必须能够继续 我遇到的问题是,重新启动队列服务器后对Python 3.x 服务器重新启动时多处理BaseManager的意外行为,python-3.x,Python 3.x,我正在构建一个由几个独立进程组成的应用程序,其中每个进程都是一个python程序。它们都由supervisord实用程序启动,并在运行Ubuntu18.04下的Python3.8.0的venv中执行 其思想是进程通过队列进行通信,因此问题是如何将队列发送到进程。我的解决方案是使用多处理管理器来实现队列存储库。每个进程按名称请求队列 由于整个应用程序需要健壮,因此如果队列服务器进程停止并重新启动(由supervisord自动启动),它必须能够继续 我遇到的问题是,重新启动队列服务器后对connec
connect()
的第一次调用不会返回队列
下面的顺序显示了一些手动测试。(我的测试环境在Windows 8.1上托管的virtualbox中运行Ubuntu)
在这里,我在另一个终端中启动了服务器,然后启动python,如下所示
这与第一次调用get_queue返回队列时的预期效果一样
(hydra_env) john@u1804-VirtualBox:~/sw/code/hydra$ python
Python 3.8.5 (default, Aug 13 2020, 15:42:06)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from multiprocessing.managers import BaseManager
>>> class QueueManager(BaseManager): pass
...
>>> QueueManager.register('get_queue')
>>> mgr = QueueManager(address=('localhost', 50000), authkey=b'abracadabra' )
>>> mgr.connect()
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<multiprocessing.queues.Queue object at 0x7f98403c1820>
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<multiprocessing.queues.Queue object at 0x7f98403c1820>
>>> mgr.connect()
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<AutoProxy[get_queue] object, typeid 'get_queue' at 0x7f280afdc160; '__str__()' failed>
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<multiprocessing.queues.Queue object at 0x7ff5f1b46820>
^C(hydra_env) john@u1804-VirtualBox:~/sw/code/hydra$ python ../../trials/test_mgr.py
starting
serving <multiprocessing.queues.Queue object at 0x7f98403c1820>
serving <multiprocessing.queues.Queue object at 0x7f98403c1820>
^C(hydra_env) john@u1804-VirtualBox:~/sw/code/hydra$ python ../../trials/test_mgr.py
starting
serving <multiprocessing.queues.Queue object at 0x7ff5f1b46820>
serving <multiprocessing.queues.Queue object at 0x7ff5f1b46820>
>>> mgr = QueueManager(address=('localhost', 50000), authkey=b'abracadabra' )
>>> mgr.connect()
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<AutoProxy[get_queue] object, typeid 'get_queue' at 0x7f280afdc2b0; '__str__()' failed>
>>> q = mgr.get_queue('name', 'src'); print(str(q))
<multiprocessing.queues.Queue object at 0x7ff8dabd7820>
>>>
from multiprocessing.managers import BaseManager
from multiprocessing import Queue
class QueueManager(BaseManager):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__queues = {} # dict of instances keyed on qname
def get_queue(self, qname: str, src: str) -> Queue:
if qname not in self.__queues:
self.__queues[qname] = Queue()
the_q = self.__queues[qname]
print(f'serving {the_q}')
return the_q
def main() -> None:
"""main for a process serving queues forever"""
mgr = QueueManager(address=('localhost', 50000), authkey=b'abracadabra' )
QueueManager.register('get_queue', callable=mgr.get_queue)
server_object = mgr.get_server()
print('starting')
server_object.serve_forever()
if __name__ == '__main__':
main()