Правильно отключить многопроцессорный удаленный менеджер

Когда используешь 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.

Другие вопросы по тегам