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

发布于 2024-11-26 18:49:50 字数 1048 浏览 0 评论 0原文

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

Is there a way to have the parent that spawned a new thread catch the spawned threads exception? Below is a real basic example of what I am trying to accomplish. It should stop counting when Exception is raised, but I don't know how to catch it. Are exceptions thread safe? I would love to be able to use the Subprocess module, but I am stuck using Python 2.3 and am not sure how else to do this. Possibly using the threading module?

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

My original code was a little misleading. It am really looking for something more like this:

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

I am trying to create a watchdog to kill the os.system call if the program hangs up for some reason.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半步萧音过轻尘 2024-12-03 18:49:50

为什么不是这样的事情

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

Why not something like this

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

This will stop the entire process. Another thing you could do is to start os.system in a different thread, then countdown and then kill that thread. Something like this,

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

system_thread = thread.start_new_thread(system_call)
time.sleep(timeout)
system_thread.kill()
似最初 2024-12-03 18:49:50

使用 Python 2.3 遇到困难

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

可能使用线程模块

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

但你可能对这个问题的思考是错误的。您可能应该创建一些类并重新考虑解决问题的方法。

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

stuck using Python 2.3

Python 2.3 is like 10 years old now. Why are you still using it?

Possibly using the threading module

You should be using threading anyway.

You are probably thinking about the problem wrong though. You should probably create some classes and rethink the approach to your problem.

Also if you're creating a watchdog, it probably doesn't make much sense to have it in the same process as what you're doing. time.sleep() is a system call that a regular python Exception won't cancel anyway.

鸠书 2024-12-03 18:49:50

如果您真正想做的是传递/处理异常,那么我认为您不想使用子进程,因为父进程只能“查看”子进程生成的状态代码(和输出) -仅在立即发生的情况下子进程中的灾难性失败会在父进程中“重新引发”异常: http ://docs.python.org/library/subprocess.html#exceptions

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

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

这个问题还有一些与您的问题相关的好答案:
在Python中捕获调用者线程中的线程异常

If what you're really trying to do is pass/handle an exception then I don't think you want to use a Subprocess, since the parent process can only "see" the status code (and output) produced by the child process - only in cases of immediate & catastrophic failure in the child process does an exception get "re-raised" in the parent: http://docs.python.org/library/subprocess.html#exceptions.

And (again if you're trying to pass/handle an exception) I'm not sure you want threads, either. After all, the whole point (IMO) of exceptions is to have something which can either be handled "by the caller" (inside a try block) or can provide meaningful backtrace information (the call sequence) if not handled. Neither idea really works with "throw" in one thread and "catch" in another.

If your real goal is to have one piece of logic "time out" another one, then I think it makes sense for your "watchdog" to be a separate process - either a "parent" that monitors output from a "child" (as well as time elapsed), or a "peer" that "watches" something like log lines and/or DB updates by the monitored process (as well as the clock). In neither case are exceptions particularly relevant. And I recommend taking a look at Alex Martelli's answer to this question: Using module 'subprocess' with timeout

This question also has a couple of good answers that are relevant to your question:
Catch a thread's exception in the caller thread in Python

予囚 2024-12-03 18:49:50

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

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

I know you're stuck using Python 2.3, but if you could only make the (very) modest advancement to Python 2.4 then you could take advantage of this more straightforward approach, copied from an answer given by Yaroslav Bulatov to a question (recommended reading) about running an external command with timeout: 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()

This is an example of a parent process timing out a child process, as mentioned in my earlier answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文