python 池 result.get() 块信号处理程序
python Pool result.get() block signal handler
我给 Pool 做了一些长时间的 运行 工作,然后做 result.get():
result = my_pool.apply_async(long_run_func)
result.get()
这里进程会被阻塞,我尝试给这个进程发送信号。然后我发现信号处理程序只会在 result.get() 完成后被调用。
这里是示例代码我运行:
import os
import sys
import atexit
import time
from threading import Thread
from multiprocessing import Pool
from signal import signal,SIGTERM,SIG_IGN
def func_in_pool():
for i in range(10):
print 'Sleeping... %d'%i
time.sleep(1)
def func_in_atexit():
print 'Calling from atexit()'
def func_in_thread():
print 'Calling from thread.'
time.sleep(4)
print 'Calling from thread: os.kill()'
os.kill(os.getpid(), SIGTERM)
def init_worker():
signal(SIGTERM, SIG_IGN)
my_pool=Pool(2, init_worker)
signal(SIGTERM, lambda signum, stack_frame: sys.exit(1))
atexit.register(func_in_atexit)
mythread = Thread(target=func_in_thread)
mythread.start()
print 'Thread has been started'
result = my_pool.apply_async(func_in_pool,[])
result.get()
time.sleep(2)
print 'After get()'
mythread.join()
我预计该过程将在 4 秒后结束,但实际上它在 10 秒后结束,这意味着 result.get() 已返回。
输出是这样的:
python myexit.py
Calling from thread.
Thread has been started
Sleeping... 0
Sleeping... 1
Sleeping... 2
Sleeping... 3
Calling from thread: os.kill()
Sleeping... 4
Sleeping... 5
Sleeping... 6
Sleeping... 7
Sleeping... 8
Sleeping... 9
Calling from atexit()
信号处理程序用于确保在 atexit 中注册的函数将被调用。我怎样才能让后台线程生成信号并立即调用信号处理程序?
(如果不把signal handler放在那里,当线程产生signal时,进程就会结束。但是,在这种情况下,atexit中注册的函数不会被调用。)
这是由 Python 中的 bug 引起的。解决方法是在 get()
中指定超时——即使是很长的超时也可以:
result.get(timeout=525600*60) # It's time now, to sing out
我给 Pool 做了一些长时间的 运行 工作,然后做 result.get():
result = my_pool.apply_async(long_run_func)
result.get()
这里进程会被阻塞,我尝试给这个进程发送信号。然后我发现信号处理程序只会在 result.get() 完成后被调用。
这里是示例代码我运行:
import os
import sys
import atexit
import time
from threading import Thread
from multiprocessing import Pool
from signal import signal,SIGTERM,SIG_IGN
def func_in_pool():
for i in range(10):
print 'Sleeping... %d'%i
time.sleep(1)
def func_in_atexit():
print 'Calling from atexit()'
def func_in_thread():
print 'Calling from thread.'
time.sleep(4)
print 'Calling from thread: os.kill()'
os.kill(os.getpid(), SIGTERM)
def init_worker():
signal(SIGTERM, SIG_IGN)
my_pool=Pool(2, init_worker)
signal(SIGTERM, lambda signum, stack_frame: sys.exit(1))
atexit.register(func_in_atexit)
mythread = Thread(target=func_in_thread)
mythread.start()
print 'Thread has been started'
result = my_pool.apply_async(func_in_pool,[])
result.get()
time.sleep(2)
print 'After get()'
mythread.join()
我预计该过程将在 4 秒后结束,但实际上它在 10 秒后结束,这意味着 result.get() 已返回。
输出是这样的:
python myexit.py
Calling from thread.
Thread has been started
Sleeping... 0
Sleeping... 1
Sleeping... 2
Sleeping... 3
Calling from thread: os.kill()
Sleeping... 4
Sleeping... 5
Sleeping... 6
Sleeping... 7
Sleeping... 8
Sleeping... 9
Calling from atexit()
信号处理程序用于确保在 atexit 中注册的函数将被调用。我怎样才能让后台线程生成信号并立即调用信号处理程序?
(如果不把signal handler放在那里,当线程产生signal时,进程就会结束。但是,在这种情况下,atexit中注册的函数不会被调用。)
这是由 Python 中的 bug 引起的。解决方法是在 get()
中指定超时——即使是很长的超时也可以:
result.get(timeout=525600*60) # It's time now, to sing out