многопроцессорный класс python BaseManager потерял соединение сразу после Ctrl-C

У меня возникают некоторые проблемы, которые, как я подозреваю, являются ограничением моей программы на Python для правильной обработки, моя программа не может вызывать методы зарегистрированного класса BaseManager сразу после того, как я нажму Ctrl-C, даже другой процесс, реализованный как классы, которые наследуют от multiprocessing.Process затронуты. У меня есть некоторые методы, которые я хотел бы вызвать из процесса, которые не выполняются правильно после Ctrl-C.

Например, следующий код не может вызвать экземпляр mt TestClass после сочетания клавиш Ctrl-C.

from multiprocessing.managers import BaseManager, NamespaceProxy
import time

class TestClass(object):
    def __init__(self, a):
        self.a = a

    def b(self):
        print self.a

class MyManager(BaseManager): pass

class TestProxy(NamespaceProxy):
    # We need to expose the same __dunder__ methods as NamespaceProxy,
    # in addition to the b method.
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'b')

    def b(self):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('b')

MyManager.register('TestClass', TestClass, TestProxy)

if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    t = TestClass(1)
    print t.a
    mt = manager.TestClass(2)
    print mt.a
    mt.a = 5
    mt.b()

    try:
        while 1:
            pass
    except (KeyboardInterrupt, SystemExit):
        time.sleep(0.1)
        mt.a = 7
        mt.b()
        print "bye"
        pass

Here is the console output

1
2
5
^CTraceback (most recent call last):
  File "testManager.py", line 38, in <module>
    mt.a = 7
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 1028, in __setattr__
    return callmethod('__setattr__', (key, value))
  File "/usr/lib/python2.7/multiprocessing/managers.py", line 758, in _callmethod
    conn.send((self._id, methodname, args, kwds))
IOError: [Errno 32] Broken pipe

Есть ли у вас предложения? Есть ли обходной путь или что-то не так в моем коде?

Заранее спасибо.


person mhanuel    schedule 06.05.2016    source источник


Ответы (2)


Если у кого-то возникла эта проблема, я решил на основе этого ответа https://stackoverflow.com/a/21106459/1667319 . Вот рабочий код

from multiprocessing.managers import SyncManager, NamespaceProxy
import time
import signal

#handle SIGINT from SyncManager object
def mgr_sig_handler(signal, frame):
    print 'not closing the mgr'

#initilizer for SyncManager
def mgr_init():
    signal.signal(signal.SIGINT, mgr_sig_handler)
    #signal.signal(signal.SIGINT, signal.SIG_IGN) # <- OR do this to just ignore the signal
    print 'initialized mananger'

class TestClass(object):
    def __init__(self, a):
        self.a = a

    def b(self):
        print self.a

class MyManager(SyncManager): pass

class TestProxy(NamespaceProxy):
    # We need to expose the same __dunder__ methods as NamespaceProxy,
    # in addition to the b method.
    _exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'b')

    def b(self):
        callmethod = object.__getattribute__(self, '_callmethod')
        return callmethod('b')

MyManager.register('TestClass', TestClass, TestProxy)

if __name__ == '__main__':
    manager = MyManager()
    manager.start(mgr_init)
    t = TestClass(1)
    print t.a
    mt = manager.TestClass(2)
    print mt.a
    mt.a = 5
    mt.b()
    try:
        while 1:
            pass
    except (KeyboardInterrupt, SystemExit):
        time.sleep(0.1)
        mt.a = 7
        mt.b()
        print "bye"
        pass

Ваше здоровье,

person mhanuel    schedule 06.05.2016

Это дубликат вопроса, и я написал там:

Самое простое решение - запустить менеджер с

manager.start(signal.signal, (signal.SIGINT, signal.SIG_IGN))

вместо менеджера.start(). И проверьте, есть ли модуль сигнала в вашем импорте (сигнал импорта).

Это ловит и игнорирует SIGINT (Ctrl-C) в процессе менеджера.

person petr    schedule 19.02.2017
comment
Это повышает PicklingError: Can't pickle <function signal at 0x000001705470BB70>: it's not the same object as _signal.signal - person Maggyero; 20.06.2019