Python - 让父线程处理子线程异常

时间:2011-07-28 23:15:51

标签: python multithreading exception parent-child watchdog

有没有办法让生成新线程的父级捕获生成的线程异常?以下是我想要完成的一个真实的基本示例。当引发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()

更新

我的原始代码有点误导。它真的在寻找更像这样的东西:

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.system调用。

4 个答案:

答案 0 :(得分:2)

  

坚持使用Python 2.3

Python 2.3现在已经10年了。你为什么还在使用它?

  

可能使用穿线模块

无论如何你应该使用线程。

你可能正在考虑这个问题。您应该创建一些类并重新考虑解决问题的方法。

另外,如果您正在创建一个监视程序,那么将它与您正在执行的程序放在同一个进程中可能没什么意义。 time.sleep()是一个系统调用,普通的python Exception无论如何都不会取消。

答案 1 :(得分:2)

如果您真正想要做的是传递/处理异常,那么我认为您不想使用Subprocess,因为父进程只能“看到”由该进程生成的状态代码(和输出)儿童过程 - 仅限于直接和子进程中的灾难性故障会在父进程中“重新引发”异常:http://docs.python.org/library/subprocess.html#exceptions

(再次,如果你试图传递/处理异常)我也不确定你是否想要线程。毕竟,异常的全部要点(IMO)是可以“由调用者”(在try块内)处理或者可以提供有意义的回溯信息(调用序列) 处理。这两种想法都不能在一个线程中“抛出”而在另一个线程中“捕获”。

如果你的真正目标是让一个逻辑“超时”另一个逻辑,那么我认为你的“看门狗”是一个独立的过程是有意义的 - 要么是一个监视“孩子”输出的“父母” “(以及经过的时间),或”监视“受监视进程(以及时钟)的日志行和/或数据库更新之类的”对等“。两种情况都不是特别相关的例外。我建议看一下Alex Martelli对这个问题的回答:Using module 'subprocess' with timeout

这个问题也有几个与你的问题相关的好答案: Catch a thread's exception in the caller thread in Python

答案 2 :(得分:2)

为什么不这样呢

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

答案 3 :(得分:1)

我知道你使用的是Python 2.3,但是如果你只能对Python 2.4进行(非常)适度的推进那么你可以利用这种更简单的方法,从Yaroslav Bulatov给出的答案复制到一个问题(推荐阅读)关于使用超时运行外部命令:Python, Popen and select - waiting for a process to terminate or a timeout

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

这是父进程超时子进程的示例,如我之前的回答中所述。