2014-09-11 35 views
2

遵循这一问题Keyboard Interrupts with python's multiprocessing Pool的一些建议,我编写了一个名为测试代码test.pyKeyboardInterrupts用python的多池IMAP

from multiprocessing import Pool 
from multiprocessing.pool import IMapIterator 
import fileinput 

def wrapper(func): 
    def wrap(self, timeout=None): 
    # Note: the timeout of 1 googol seconds introduces a rather subtle 
    # bug for Python scripts intended to run many times the age of the universe. 
    return func(self, timeout=timeout if timeout is not None else 1e100) 
return wrap 
IMapIterator.next = wrapper(IMapIterator.next) 

def main(): 
    p = Pool(1) 
    try: 
     for _ in p.imap(worker, fileinput.input(), 1): 
      pass 
    except KeyboardInterrupt: 
     p.terminate() 

def worker(line): 
    print line 

if __name__ == '__main__': 
    main() 

当我运行在终端的python test.py:

python test.py 

我仍然得到了KeyboardInterrupt回溯,此外我必须发送Ctrl^C两次来停止脚本。我如何处理KeyboardInterrupt并让它不打印tarceback,只用一次Ctrl^c就可以正常停止它。

^CProcess PoolWorker-1: 
Traceback (most recent call last): 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 102, in worker 
    task = get() 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/queues.py", line 376, in get 
    return recv() 
KeyboardInterrupt 
^CTraceback (most recent call last): 
File "test.py", line 27, in <module> 
    main() 
File "test.py", line 21, in main 
    p.terminate() 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 452, in terminate 
    self._worker_handler._state = TERMINATE 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/util.py", line 201, in __call__ 
    res = self._callback(*self._args, **self._kwargs) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 504, in _terminate_pool 
    if threading.current_thread() is not task_handler: 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 958, in join 
    self.__block.wait(delay) 
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 358, in wait 
    _sleep(delay) 
KeyboardInterrupt 
+0

对不起你的问题是什么? – 2014-09-11 09:23:59

+0

@MehdiNellen thx你的回复,我编辑我的帖子 – leopay 2014-09-11 09:28:27

回答

3

看看标准库中包含的信号模块。您可以在主进程中注册信号处理程序

from signal import * 

def siginthndlr(sig, frame): 
    '''do what you need here''' 
    print "Keyboard interrupt catched" 

signal(SIGINT, siginthndlr) #Register SIGINT handler function 

将优雅地杀死工作进程并杀死主进程。

+0

我在siginthndlr添加sys.exit(0),没有回溯输出,因为我想 – leopay 2014-09-11 10:44:39

+0

但我仍然需要发送Ctrl^c两次 – leopay 2014-09-11 10:45:12

+0

@leopay,我想这是因为你在杀死主流程之前需要以某种方式杀死工人。 – wWolfovich 2014-09-11 11:09:32