我正在尝试使用Ctrl + C优雅地停止运行的代码,包括本地dask.distrubted客户端。下面的代码是我的设置示例。当我使用Ctrl + C时,将正确调用stop()方法,但是dask Client似乎在到达self.dask.close()方法之前就不正确地退出/打印了回溯。
from dask.distributed import Client
class SomeService(object):
def __init__(self):
self.dask = None
def run(self):
# Setup local dask client
self.dask = Client()
while True:
# Do something blocking
def stop(self):
# Close dask client
print('Closing Dask Client...')
self.dask.close()
print('Dask Cient closed.')
# Stop other stuff
# ...
print('SomeService has been stopped.')
if __name__ == '__main__':
service = SomeService()
try:
service.run()
except KeyboardInterrupt:
print('Keyboard interrupt received.')
service.stop()
这是我收到的输出:
^CTraceback (most recent call last):
File "<string>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/forkserver.py", line 170, in main
rfds = [key.fileobj for (key, events) in selector.select()]
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/selectors.py", line 560, in select
kev_list = self._kqueue.control(None, max_ev, timeout)
KeyboardInterrupt
Keyboard interrupt received.
Closing Dask Client...
Dask Client closed.
SomeService has been stopped.
我已尽力使google / stack溢出此问题,而我发现的唯一解决方案是使用信号包强制回调SIGINT的建议。但是,如果要在单独的线程中运行SomeService类,则此解决方案将不起作用,因为您只能对主线程上的信号强制执行信号回调。
任何建议将不胜感激。这不是保持和管理Dask Client / LocalClient的正确方法吗?
其他信息:
Python 3.5.1
dask==0.19.2
distributed==1.23.2
tornado==5.0.2
答案 0 :(得分:0)
使用设置标志的信号处理程序。交付后,将导致IOError异常(将.errno
成员设置为errno.EINTR
):
import signal
done = False
def done_handler(signum, frame):
done = True
if __name__ == '__main__':
signal.signal(signal.SIGINT, done_handler)
service = SomeService()
while not done:
try:
service.run()
except IOError:
break
service.stop()
在Python中,信号始终在主线程中传递,并且处理程序始终在主线程中执行,因此,除非捕获到IOError异常,否则它应渗透到service.run()
。 (在您的示例中,KeyboardInterrupt会这样做。)当捕获到该异常时,服务将停止。