2016-05-06 17 views
1

Ich habe einige Probleme, die ich vermute, ist eine Einschränkung meines Python-Programms korrekt zu handhaben, mein Programm war nicht in der Lage, Methoden einer registrierten Klasse von BaseManager sofort aufzurufen nachdem ich Ctrl-C gedrückt habe, sind sogar andere Prozesse betroffen, die als Klassen implementiert sind, die von Multiprocessing.Process erben. Ich habe einige Methoden, die ich vom Prozess aufrufen möchte, die nach Ctrl-C nicht korrekt ausgeführt werden.Python Multiprocessing BaseManager registrierte Klasse Verbindung verloren sofort nach Ctrl-C

Zum Beispiel ist der folgende Code nicht in der Lage, die mt-Instanz von TestClass nach Ctrl-C aufzurufen.

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 

Haben Sie Vorschläge? Gibt es eine Problemumgehung oder etwas in meinem Code falsch?

Vielen Dank im Voraus.

Antwort

0

Wenn jemand dieses Problem hatte, löste ich basierend auf dieser Antwort https://stackoverflow.com/a/21106459/1667319. Hier ist der Arbeitscode

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 

Cheers,

0

Dies zu question duplizieren und ich schrieb es:

Simplest Lösung - Start-Manager mit

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

statt manager.start(). Und prüfen Sie, ob sich das Signalmodul in Ihren Importen befindet (Importsignal).

Dies fangen und ignorieren SIGINT (Ctrl-C) im Manager-Prozess.