Python - родительский поток обрабатывает исключение дочерних потоков - PullRequest
5 голосов
/ 29 июля 2011

Есть ли способ, чтобы родитель, который породил новый поток, перехватывал исключение порожденных потоков? Ниже приведен реальный базовый пример того, чего я пытаюсь достичь. Он должен перестать считать, когда возбуждается Exception, но я не знаю, как его поймать. Безопасны ли исключения потока? Мне бы очень хотелось иметь возможность использовать модуль Subprocess, но я застрял на Python 2.3 и не уверен, как еще это сделать. Возможно использование модуля threading?

import time
import thread

def test(): 
    try:
        test = thread.start_new_thread(watchdog, (5,))
        count(10)
    except:
        print('Stopped Counting')

def count(num):
    for i in range(num):
        print i
        time.sleep(1)

def watchdog(timeout):
    time.sleep(timeout)
    raise Exception('Ran out of time')

if __name__ == '__main__':
    test()

UPDATE

Мой оригинальный код немного вводил в заблуждение. Это действительно ищет что-то еще, как это:

import time
import thread
import os

def test(): 
    try:
        test = thread.start_new_thread(watchdog, (5,))
        os.system('count_to_10.exe')
    except:
        print('Stopped Counting')

def watchdog(timeout):
    time.sleep(timeout)
    raise Exception('Ran out of time')

if __name__ == '__main__':
    test()

Я пытаюсь создать сторожевой таймер для завершения системного вызова os.s, если программа по какой-то причине зависает.

Ответы [ 4 ]

2 голосов
/ 29 июля 2011

Если то, что вы действительно пытаетесь сделать, это передать / обработать исключение, тогда я не думаю, что вы хотите использовать подпроцесс, поскольку родительский процесс может только «видеть» код состояния (и вывод), созданный дочерний процесс - только в случаях немедленного и катастрофического сбоя в дочернем процессе исключение «перебрасывается» в родительском процессе: http://docs.python.org/library/subprocess.html#exceptions.

И (опять же, если вы пытаетесь передать / обработать исключение), я тоже не уверен, что вам нужны потоки. В конце концов, весь смысл (IMO) исключений состоит в том, чтобы иметь что-то, что может быть обработано «вызывающей стороной» (внутри блока try) или может предоставить значимую информацию обратной трассировки (последовательность вызовов), если не обработано. Ни одна из этих идей на самом деле не работает с «throw» в одном потоке и «catch» в другом.

Если ваша настоящая цель состоит в том, чтобы одна часть логики «вышла из строя» другой, то я думаю, что ваш «сторожевой таймер» имеет смысл быть отдельным процессом - либо «родителем», который отслеживает вывод «потомка» "(а также прошедшее время), или" одноранговый узел ", который" наблюдает "что-то вроде строк журнала и / или обновлений БД отслеживаемым процессом (а также часами). Ни в том, ни в другом случае исключения не имеют особого значения. И я рекомендую взглянуть на ответ Алекса Мартелли на этот вопрос: Использование модуля 'подпроцесс' с таймаутом

На этот вопрос также есть несколько хороших ответов, которые имеют отношение к вашему вопросу: Перехватить исключение потока в потоке вызывающего в Python

2 голосов
/ 07 августа 2011

Почему бы не что-то подобное

def test(): 
    def exeption_cb():
        os._exit()
    test = thread.start_new_thread(watchdog, (5, exception_cb))
    os.system('count_to_10.exe')
    print('Stopped Counting')

def watchdog(timeout, callback):
    time.sleep(timeout)
    callback()

Это остановит весь процесс.Другая вещь, которую вы можете сделать, это запустить os.system в другом потоке, затем выполнить обратный отсчет и затем убить этот поток.Как то так,

def system_call():
    os.system('count_to_10.exe')

system_thread = thread.start_new_thread(system_call)
time.sleep(timeout)
system_thread.kill()
2 голосов
/ 29 июля 2011

застрял с помощью Python 2.3

Python 2.3 уже 10 лет.Почему вы все еще используете это?

Возможно использование модуля потоков

В любом случае, вы должны использовать потоки.

Вы, вероятно, думаете о проблеме неправильно, хотя.Вероятно, вам следует создать несколько классов и переосмыслить подход к вашей проблеме.

Также, если вы создаете сторожевой таймер, вероятно, не имеет смысла включать его в тот же процесс, что и вы.,time.sleep () - системный вызов, который обычный питон Exception не отменит в любом случае.

1 голос
/ 10 августа 2011

Я знаю, что вы застряли с использованием Python 2.3, но если бы вы могли сделать (очень) скромное продвижение к Python 2.4, вы могли бы воспользоваться этим более простым подходом, скопированным из ответа Ярослава Булатова на вопрос(рекомендуется прочитать) о запуске внешней команды с тайм-аутом: Python, Popen и select - ожидание завершения процесса или тайм-аут

from threading import Timer
from subprocess import Popen, PIPE

def kill_proc():
    proc.kill()

proc = Popen("count_to_10.exe", shell=True)
t = Timer(60, kill_proc)
t.start()
proc.wait()

Это пример родительского процессавремя ожидания дочернего процесса, как упоминалось в моем предыдущем ответе.

...