8

有没有办法让产生新线程的父级捕获产生的线程异常?下面是我想要完成的一个真实的基本示例。当引发异常时它应该停止计数,但我不知道如何捕捉它。异常线程安全吗?我希望能够使用该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

4 回答 4

3

为什么不这样

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()
于 2011-08-07T18:14:58.327 回答
2

坚持使用 Python 2.3

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

可能使用线程模块

无论如何,您应该使用线程。

不过,您可能正在考虑错误的问题。您可能应该创建一些类并重新考虑解决问题的方法。

此外,如果您正在创建一个看门狗,那么将它与您正在做的事情放在同一个过程中可能没有多大意义。time.sleep() 是一个常规 pythonException无论如何都不会取消的系统调用。

于 2011-07-28T23:53:53.833 回答
2

如果您真正想做的是传递/处理异常,那么我认为您不想使用子进程,因为父进程只能“看到”子进程产生的状态代码(和输出)-只有在子进程发生直接和灾难性故障的情况下,父进程才会“重新引发”异常: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

于 2011-07-29T00:37:00.457 回答
1

我知道您在使用 Python 2.3 时遇到了困难,但是如果您只能对 Python 2.4 做出(非常)适度的改进,那么您可以利用这种更直接的方法,从 Yaroslav Bulatov 对问题的回答中复制而来(推荐阅读) 关于超时运行外部命令: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()

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

于 2011-08-09T23:14:04.337 回答