我遇到了一个问题,无法优雅地处理Python多进程中的键盘中断。
(是的,我知道Ctr-C不能保证优雅关闭——但让我们将这个讨论留到另一个主题中)
请考虑以下代码,我使用了 multiprocessing.Manager#list()
,它是一个ListProxy,我了解到它可以处理对列表的多进程访问。
当我使用Ctr-C时,尝试访问ListProxy时会出现socket.error: [Errno 2] No such file or directory
错误。
我希望在使用Ctr-C时共享列表不会被破坏。这可能吗?!
注意:我希望在不使用池和队列的情况下解决此问题。
from multiprocessing import Process, Manager
from time import sleep
def f(process_number, shared_array):
try:
print "starting thread: ", process_number
shared_array.append(process_number)
sleep(3)
shared_array.append(process_number)
except KeyboardInterrupt:
print "Keyboard interrupt in process: ", process_number
finally:
print "cleaning up thread", process_number
if __name__ == '__main__':
processes = []
manager = Manager()
shared_array = manager.list()
for i in xrange(4):
p = Process(target=f, args=(i, shared_array))
p.start()
processes.append(p)
try:
for process in processes:
process.join()
except KeyboardInterrupt:
print "Keyboard interrupt in main"
for item in shared_array:
# raises "socket.error: [Errno 2] No such file or directory"
print item
如果你运行它,然后按下Ctrl-C,我们会得到以下结果:
starting thread: 0
starting thread: 1
starting thread: 3
starting thread: 2
^CKeyboard interupt in process: 3
Keyboard interupt in process: 0
cleaning up thread 3
cleaning up thread 0
Keyboard interupt in process: 1
Keyboard interupt in process: 2
cleaning up thread 1
cleaning up thread 2
Keyboard interupt in main
Traceback (most recent call last):
File "multi.py", line 33, in <module>
for item in shared_array:
File "<string>", line 2, in __getitem__
File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 755, in _callmethod
self._connect()
File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/managers.py", line 742, in _connect
conn = self._Client(self._token.address, authkey=self._authkey)
File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 169, in Client
c = SocketClient(address)
File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/connection.py", line 293, in SocketClient
s.connect(address)
File "/usr/local/Cellar/python/2.7.3/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 2] No such file or directory
这里是另一种方法,使用 multiprocessing.Lock
实现类似的效果 ... gist
signal.signal(signal.SIGINT, signal.SIG_IGN)
- Jonathanthreading.Thread
替换multiprocessing.Process
,运行程序并按下Ctrl+C,SIGINT
信号不会发送给主进程和管理器子进程,而只会发送给后者? - Géry Ogam