Python: невозможно убить процесс с помощью прерывания клавиатуры? - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть декоратор, записанный так:

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()

(извините за все обновления)

1 Ответ

0 голосов
/ 01 февраля 2019

Из темы Документация :

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()
...