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.
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()
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.
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
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.
精彩评论