5

当使用multiprocessingManager 对象创建服务器并远程连接到该服务器时,客户端需要保持与远程服务器的连接。如果服务器在客户端关闭之前就消失了,客户端将永远尝试连接到服务器的预期地址。

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

如果我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()

更新这在多处理中被破坏了。连接超时需要在套接字级别发生(并且套接字需要是非阻塞的才能做到这一点),但非阻塞套接字会破坏多处理。如果远程服务器不可用,则无法处理放弃建立连接。

4

2 回答 2

1

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

是的,但这是一个 hack。我希望有更好的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 中公开超时。

希望有帮助。

于 2012-03-30T04:00:16.483 回答
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 循环中进行测试。

于 2011-08-29T13:24:03.377 回答