正确断开多处理远程管理器

时间:2011-06-28 20:45:58

标签: python connection multiprocessing disconnect

使用multiprocessing Manager对象创建服务器并远程连接到该服务器时,客户端需要维护与远程服务器的连接。如果服务器在客户端关闭之前消失,则客户端将尝试永久连接到服务器的预期地址。

我在客户端代码上遇到死锁,试图在服务器消失后退出,因为我的客户端进程永远不会退出。

如果我del我的远程对象和我的客户经理在服务器关闭之前,该过程将正常退出,但在使用后立即删除我的客户端管理器对象和远程对象是不太理想的。

这是我能做的最好的吗?是否有另一种(更合适的)方法断开与远程管理器对象的连接?有没有办法在服务器关闭和/或连接丢失后干净地退出客户端?

我知道socket.setdefaulttimeout不能用于多处理,但是有没有办法专门为多处理模块设置连接超时?这是我遇到问题的代码:

from multiprocessing.managers import BaseManager
m = BaseManager(address=('my.remote.server.dns', 50000), authkey='mykey')
# this next line hangs forever if my server is not running or gets disconnected
m.connect()

更新这在多处理中被破坏了。连接超时需要在套接字级别发生(并且套接字需要非阻塞才能执行此操作),但非阻塞套接字会中断多处理。如果远程服务器不可用,则无法处理放弃连接的问题。

2 个答案:

答案 0 :(得分:1)

  

有没有办法专门为多处理模块设置连接超时?

是的,但这是一个黑客攻击。我希望有更多python-fu的人可以改善这个答案。多处理的超时在multiprocessing/connection.py

中定义
# A very generous timeout when it comes to local connections...
CONNECTION_TIMEOUT = 20.
...
def _init_timeout(timeout=CONNECTION_TIMEOUT):
        return time.time() + timeout

具体来说,我能够使其工作的方式是通过猴子修补_init_timeout方法,如下所示:

import sys
import time

from multiprocessing import managers, connection

def _new_init_timeout():
    return time.time() + 5

sys.modules['multiprocessing'].__dict__['managers'].__dict__['connection']._init_timeout = _new_init_timeout
from multiprocessing.managers import BaseManager
m = BaseManager(address=('somehost', 50000), authkey='secret')
m.connect()

其中5是新的超时值。如果有更简单的方法,我相信有人会指出它。如果没有,这可能是多处理开发团队的功能请求的候选者。我认为设置超时的基本内容应该比这更容易。另一方面,他们可能有哲学原因不在API中暴露超时。

希望有所帮助。

答案 1 :(得分:0)

这可以帮到你吗?

#### TEST_JOIN_TIMEOUT

def join_timeout_func():
    print '\tchild sleeping'
    time.sleep(5.5)
    print '\n\tchild terminating'

def test_join_timeout():
    p = multiprocessing.Process(target=join_timeout_func)
    p.start()

    print 'waiting for process to finish'

    while 1:
        p.join(timeout=1)
        if not p.is_alive():
            break
        print '.',
        sys.stdout.flush()

(摘自python 16.6页)

通常,在一些while循环中测试超时。