首页 > 解决方案 > Python:无法通过键盘中断终止进程?

问题描述

我有一个这样写的装饰器:

import threading
from time import sleep
from functools import wraps
import sys
import os

def repeat_periodically(f):
    """ Repeat wrapped function every second """
    @wraps(f)
    def wrap(self, *args, **kwargs):
        def wrap_helper(*args, **kwargs):
            try:
                threading.Timer(1.0, wrap_helper).start()
                f(self)
            except KeyboardInterrupt:
                try:
                    sys.exit(1)
                except:
                    os._exit(1)

        wrap_helper()

    return wrap

我不确定它是否会在每次调用自身时继续打开一个新线程,但无论如何,当我点击CTRL + C. 我还在try-except我装饰的函数中添加了相同的块:

@repeat_periodically
def get_stats(self):
    try:
        # log some state information
    except KeyboardInterrupt:
        try:
            sys.exit(1)
        except:
            os._exit(1)

我的程序继续运行,我在终端中看到的只是

^C <the stuff that I am logging>
<the stuff that I am logging>
<the stuff that I am logging>

换句话说,它只是继续记录,即使我试图用CTRL + C.

更新:

我应该提到,上述过程是从另一个线程中分离出来的:

tasks = [
    {'target': f, 'args': (arg1)},
    {'target': g},
]
for task in tasks:
    t = threading.Thread(**task)
    t.start()

具体来说,它是启动计时器的第二个任务。但是,如果我设置t.daemon = True,该过程只运行一次并退出。第一个任务使用watchdog。我基本上使用了看门狗文档中的示例代码:

def watch_for_event_file(Event):
    path = sys.argv[1] if len(sys.argv) > 1 else '.'
    event_handler = LoggingCreateHandler(Event)
    observer = Observer()
    observer.schedule(event_handler, path)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

(抱歉所有更新)

标签: pythonkill

解决方案


从线程文档

The entire Python program exits when no alive non-daemon threads are left.

因此,将您的Timer线程作为守护线程应该可以解决您的问题。所以替换:

threading.Timer(1.0, wrap_helper).start()

和:

t = threading.Timer(1.0, wrap_helper)
t.daemon = True
t.start()

推荐阅读