Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

python - Timeout a function (windows)?

I am trying to implement timeout for a particular function. I have checked many of the questions in SE and couldn't find any solution which fits my problem, because:

  1. I am running python in Windows
  2. Timeout is applied on a python function which I don't have control on, i.e. it is defined in an already designed module.
  3. The python function is not a subprocess

I am having a already designed custom module (say MyModule) developed for particular tasks, and there are functions defined in it. One of the function (say MyFunc) has a tendency to run forever because of external factors, and I just don't want the python script to hang.

I am planning to add a timeout feature, as said below pseudocode:

import MyModule

set_timeout(T)
MyResult=MyModule.MyFunc()

#Come to this part of script after execution of MyFunc() or after T seconds (the latter on priority)
if Timeout occurred:
    print 'MyFunc did not execute completely'
else:
    print 'MyFunc completed'

But I am not sure which module can be used to achieve this on python. Note that I am a newbie, and all the scripts I have written are directly based on SE Answers or Python Documentation.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think a good way to approach this is to create a decorator and use the Thread.join(timeout=seconds) method. Bear in mind that there's no good way to kill the thread, so it will continue to run in the background, more or less, as long as your program is running.

First, create a decorator like this:

from threading import Thread
import functools

def timeout(timeout):
    def deco(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            res = [Exception('function [%s] timeout [%s seconds] exceeded!' % (func.__name__, timeout))]
            def newFunc():
                try:
                    res[0] = func(*args, **kwargs)
                except Exception as e:
                    res[0] = e
            t = Thread(target=newFunc)
            t.daemon = True
            try:
                t.start()
                t.join(timeout)
            except Exception as je:
                print ('error starting thread')
                raise je
            ret = res[0]
            if isinstance(ret, BaseException):
                raise ret
            return ret
        return wrapper
    return deco

Then, do something like this:

func = timeout(timeout=16)(MyModule.MyFunc)
try:
    func()
except:
    pass #handle errors here

You can use this decorator anywhere you need with something like:

@timeout(60)
def f():
    ...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...