2

我遇到了一些我怀疑是我的 python 程序无法正确处理的问题,我的程序无法在按下 Ctrl-C 后立即调用 BaseManager 的注册类的方法,甚至其他进程实现为继承的类从 multiprocessing.Process 受到影响。我有一些我想从 Ctrl-C 后无法正确执行的进程调用的方法。

例如下面的代码不能在 Ctrl-C 之后调用 TestClass 的 mt 实例。

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

你有什么建议吗?我的代码中是否有任何解决方法或问题?

提前致谢。

4

2 回答 2

1

如果有人碰巧遇到这个问题,我根据这个答案解决了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

干杯,

于 2016-05-06T16:27:46.850 回答
0

这是重复的问题,我在那里写道:

最简单的解决方案 - 启动管理器

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

而不是 manager.start()。并检查信号模块是否在您的导入中(导入信号)。

这会在管理器进程中捕获并忽略 SIGINT (Ctrl-C)。

于 2017-02-19T15:37:31.090 回答