Правильно отключить многопроцессорный удаленный менеджер
Когда используешь multiprocessing
Диспетчер объектов для создания сервера и удаленного подключения к этому серверу, клиент должен поддерживать соединение с удаленным сервером. Если сервер отключается до того, как клиент выключится, он всегда будет пытаться подключиться к ожидаемому адресу сервера.
Я захожу в тупик на клиентском коде, пытающемся выйти после того, как сервер ушел, поскольку мой клиентский процесс никогда не завершается.
Если я 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 ответа
Есть ли способ установить время ожидания подключения для многопроцессорного модуля?
Да, но это взломать. Я надеюсь, что кто-то с большим питон-фу сможет улучшить этот ответ. Тайм-аут для многопроцессорной обработки определяется в 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.
Надеюсь, это поможет.
Может ли это помочь вам?
#### 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.