【问题标题】:Python - Have parent thread handle child threads ExceptionPython - 让父线程处理子线程异常
【发布时间】:2011-10-15 13:33:18
【问题描述】:

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

【问题讨论】:

  • 你想达到什么目的,看起来你想从子线程向父线程发送一些事件?还是你真的想传递异常?
  • 我正在尝试终止 os.system 调用,如果它需要很长时间,很可能不是正确的方法。

标签: python multithreading exception parent-child watchdog


【解决方案1】:

为什么不这样

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

【讨论】:

  • thread.kill 是我想要完成的,但不幸的是该命令不存在。
  • 但是 os.kill 确实存在,并且工作正常。 stackoverflow.com/questions/337863/… 的几个答案演示了如何让父级执行带有超时的系统调用,这似乎是您真正想要实现的目标。
  • 使用Subprocess 模块就像使用Subprocess 模块一样棒,因为正如我在原始帖子中所述,我无法使用2.3。我试图找到解决此问题的方法,但在我能够迁移到 python 2.4 或更高版本之前,我似乎无法做到。到目前为止,用于我正在使用的程序的模块是在 2.3 中编译的,并且在 2.4+ 中不起作用。
  • thread.kill() 必须手动编码。请尝试线程模块并使用基于类的线程。你可以用它完成很多工作。
【解决方案2】:

坚持使用 Python 2.3

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

可能使用线程模块

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

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

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

【讨论】:

  • 我一直坚持使用 2.3,因为 PSS/E rev 30 python 模块是在其中编译的,也是我们使用的。
【解决方案3】:

如果您真正想做的是传递/处理异常,那么我认为您不想使用子进程,因为父进程只能“看到”由子进程 - 只有在子进程发生直接和灾难性故障的情况下,父进程才会“重新引发”异常:http://docs.python.org/library/subprocess.html#exceptions

而且(同样,如果您尝试传递/处理异常)我也不确定您是否想要线程。毕竟,异常的全部意义 (IMO) 是有一些东西可以“由调用者”处理(在 try 块内),或者可以提供 有意义的 回溯信息(调用序列),如果处理。这两种想法都不能真正适用于一个线程中的“throw”和另一个线程中的“catch”。

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

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

【讨论】:

  • 如果由于某种原因挂断了os.system 呼叫,我将尝试终止它。所以我试图在生成的看门狗返回异常时杀死父进程。除了os.systemos.popen 之外,还有什么我可以调用的会立即在Python 中继续,我可以在while 循环中保持直到超时或完成?
  • 你还是想得太具体了。告诉我们你想要完成什么。 I am trying to kill a os.system call if for some reason it hangs up. 您将很难找到真正的解决方案。你的问题很可能是系统调用挂了,而不是你不能中断它。
  • 或者你可以这样想(顺便说一下,这不是 Python 特有的)——如果有一个系统调用可能由于某种原因“挂起”而你无法控制,那么你使 parent 进程成为“看门狗”,并让 child 进程成为实际运行系统调用的进程。然后,父进程可以通过各种方式监视子进程——例如,子进程可以将“心跳”消息写入由父进程监视的 STDOUT(例如每 30 秒),并且父进程可以决定子进程何时“挂起” " 并在必要时杀死它。
  • Falmarri - 很简单,我正在调用一个非 python 程序(在本例中为 count_to_10.exe),我的 python 程序必须等到它完成才能继续。现在考虑 count_to_number 而不是 count_to_10,而这个数字是无穷大。我想要一个看门狗来查看非python程序是否花费太长时间并停止它,然后引发异常。
【解决方案4】:

我知道您在使用 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()

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-27
    • 2011-02-07
    • 2013-09-10
    • 2013-10-06
    • 2014-03-23
    • 1970-01-01
    • 2015-01-11
    • 2011-12-31
    相关资源
    最近更新 更多