Coder Social home page Coder Social logo

kata198 / func_timeout Goto Github PK

View Code? Open in Web Editor NEW
298.0 13.0 35.0 125 KB

Python module which allows you to specify timeouts when calling any existing function, and support for stoppable threads

License: GNU Lesser General Public License v3.0

Python 98.69% Shell 1.31%
python pydoc function stop thread stoppablethread decorator

func_timeout's Introduction

func_timeout

Python module to support running any existing function with a given timeout.

Function Timeout

func_timeout

This is the function wherein you pass the timeout, the function you want to call, and any arguments, and it runs it for up to #timeout# seconds, and will return/raise anything the passed function would otherwise return or raise.

def func_timeout(timeout, func, args=(), kwargs=None):
	'''
		func_timeout - Runs the given function for up to #timeout# seconds.

		Raises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut

		@param timeout <float> - Maximum number of seconds to run #func# before terminating
		@param func <function> - The function to call
		@param args    <tuple> - Any ordered arguments to pass to the function
		@param kwargs  <dict/None> - Keyword arguments to pass to the function.

		@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised

		@return - The return value that #func# gives
	'''

Example

So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to limit to running for 5 seconds, with func_timeout you can call it like this:

from func_timeout import func_timeout, FunctionTimedOut

...

try:

	doitReturnValue = func_timeout(5, doit, args=('arg1', 'arg2'))

except FunctionTimedOut:
	print ( "doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.\n")
except Exception as e:
	# Handle any exceptions that doit might raise here

func_set_timeout

This is a decorator you can use on functions to apply func_timeout.

Takes two arguments, "timeout" and "allowOverride"

If "allowOverride" is present, an optional keyword argument is added to the wrapped function, 'forceTimeout'. When provided, this will override the timeout used on this function.

The "timeout" parameter can be either a number (for a fixed timeout), or a function/lambda. If a function/lambda is used, it will be passed the same arguments as the called function was passed. It should return a number which will be used as the timeout for that paticular run. For example, if you have a method that calculates data, you'll want a higher timeout for 1 million records than 50 records.

Example:

@func_set_timeout(2.5)
def myFunction(self, arg1, arg2):
	...

FunctionTimedOut

Exception raised if the function times out.

Has a "retry" method which takes the following arguments:

* No argument - Retry same args, same function, same timeout
* Number argument - Retry same args, same function, provided timeout
* None - Retry same args, same function, no timeout

How it works

func_timeout will run the specified function in a thread with the specified arguments until it returns, raises an exception, or the timeout is exceeded. If there is a return or an exception raised, it will be returned/raised as normal.

If the timeout has exceeded, the "FunctionTimedOut" exception will be raised in the context of the function being called, as well as from the context of "func_timeout". You should have your function catch the "FunctionTimedOut" exception and exit cleanly if possible. Every 2 seconds until your function is terminated, it will continue to raise FunctionTimedOut. The terminating of the timed-out function happens in the context of the thread and will not block main execution.

StoppableThread

StoppableThread is a subclass of threading.Thread, which supports stopping the thread (supports both python2 and python3). It will work to stop even in C code.

The way it works is that you pass it an exception, and it raises it via the cpython api (So the next time a "python" function is called from C api, or the next line is processed in python code, the exception is raised).

Using StoppableThread

You can use StoppableThread one of two ways:

As a Parent Class

Your thread can extend func_timeout.StoppableThread.StoppableThread and implement the "run" method, same as a normal thread.

from func_timeout.StoppableThread import StoppableThread

class MyThread(StoppableThread):

	def run(self):
		
		# Code here
		return

Then, you can create and start this thread like:

myThread = MyThread()

# Uncomment next line to start thread in "daemon mode" -- i.e. will terminate/join automatically upon main thread exit

#myThread.daemon = True

myThread.start()

Then, at any time during the thread's execution, you can call .stop( StopExceptionType ) to stop it ( more in "Stopping a Thread" below

Direct Thread To Execute A Function

Alternatively, you can instantiate StoppableThread directly and pass the "target", "args", and "kwargs" arguments to the constructor

myThread = StoppableThread( target=myFunction, args=('ordered', 'args', 'here'), kwargs={ 'keyword args' : 'here' } )

# Uncomment next line to start thread in "daemon mode" -- i.e. will terminate/join automatically upon main thread exit

#myThread.daemon = True

myThread.start()

This will allow you to call functions in stoppable threads, for example handlers in an event loop, which can be stopped later via the .stop() method.

Stopping a Thread

The StoppableThread class (you must extend this for your thread) adds a function, stop, which can be called to stop the thread.

def stop(self, exception, raiseEvery=2.0):
	'''
		Stops the thread by raising a given exception.

		@param exception <Exception type> - Exception to throw. Likely, you want to use something

		  that inherits from BaseException (so except Exception as e: continue; isn't a problem)

		  This should be a class/type, NOT an instance, i.e.  MyExceptionType   not  MyExceptionType()


		@param raiseEvery <float> Default 2.0 - We will keep raising this exception every #raiseEvery seconds,

			until the thread terminates.

			If your code traps a specific exception type, this will allow you #raiseEvery seconds to cleanup before exit.

			If you're calling third-party code you can't control, which catches BaseException, set this to a low number
			 
			  to break out of their exception handler.


		 @return <None>
	'''

The "exception" param must be a type, and it must be instantiable with no arguments (i.e. MyExceptionType() must create the object).

Consider using a custom exception type which extends BaseException, which you can then use to do basic cleanup ( flush any open files, etc. ).

The exception type you pass will be raised every #raiseEvery seconds in the context of that stoppable thread. You can tweak this value to give yourself more time for cleanups, or you can shrink it down to break out of empty exception handlers ( try/except with bare except ).

Notes on Exception Type

It is recommended that you create an exception that extends BaseException instead of Exception, otherwise code like this will never stop:

while True:
	try:
		doSomething()
	except Exception as e:
		continue

If you can't avoid such code (third-party lib?) you can set the "repeatEvery" to a very very low number (like .00001 ), so hopefully it will raise, go to the except clause, and then raise again before "continue" is hit.

You may want to consider using singleton types with fixed error messages, so that tracebacks, etc. log that the call timed out.

For example:

class ServerShutdownExceptionType(BaseException):

	def __init__(self, *args, **kwargs):

		BaseException.__init__(self, 'Server is shutting down')

This will force 'Server is shutting down' as the message held by this exception.

Pydoc

Find the latest pydoc at http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=4.3.5 .

Support

I've tested func_timeout with python 2.7, 3.4, 3.5, 3.6, 3.7. It should work on other versions as well.

Works on windows, linux/unix, cygwin, mac

ChangeLog can be found at https://raw.githubusercontent.com/kata198/func_timeout/master/ChangeLog

Pydoc can be found at: http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=1

func_timeout's People

Contributors

kata198 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

func_timeout's Issues

Nested exception in gethostbyname

If I run:

import func_timeout
import time
import socket

print('starting socket.gethostbyname')
try:
    # function gethostbyname normally returns within 40ms (even on VPN); a value
    # of 200ms should be ample and not give a noticeable delay
    if func_timeout.func_timeout(0.2, socket.gethostbyname,
                                 args=('anyname.local',)) == '192.168.1.51':
        print('socket.gethostbyname got a valid name')
except func_timeout.FunctionTimedOut:
    print('socket.gethostbyname timed out')
except Exception as e:
    # handle any exceptions that socket.gethostbyname might raise here
    print('socket.gethostbyname raised exception {}'.format(e))
print('finished socket.gethostbyname')
count = 20
while count > 0:
    time.sleep(1)
    count -= 1
print('finished while')

Then gethostbyname times out, as intended, but I get a nested exception after around 12 seconds. Output:

starting socket.gethostbyname
socket.gethostbyname timed out
finished socket.gethostbyname

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\projects\python\venv3_pyside2\lib\site-packages\func_timeout\dafunc.py", line 68, in funcwrap
    ret.append( func(*args2, **kwargs2) )
socket.gaierror: [Errno 11001] getaddrinfo failed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\geert.SALCOM\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\geert.SALCOM\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "C:\projects\python\venv3_pyside2\lib\site-packages\func_timeout\dafunc.py", line 68, in funcwrap
    ret.append( func(*args2, **kwargs2) )
func_timeout.dafunc.FunctionTimedOut-1191607612: Function gethostbyname (args=('anyname.local',)) (kwargs={}) timed out after 0.200000 seconds.

finished while

It seems that the background thread that runs gethostbyname isn't terminated. It generates exception socket.gaierror after it times out and this clashes with func_timeout exception func_timeout.FunctionTimedOut.

The 'around 12 seconds' is the time gethostbyname times out if I run it normally (without func-timeout).

No such file or directory: '/dev/null'

In Windows there is no '/dev/null' so when a timeout is reached the code throws this exception

func_timeout\StoppableThread.py", line 24, in _stopThread
self._stderr = open('/dev/null', 'w')
IOError: [Errno 2] No such file or directory: '/dev/null'

Different license versions

The code currently states different versions of the LGPL. Which is the correct one?

Current statements:

  • LGPLv2.1:
    This software is licensed under the terms of the Lesser GNU General Public License Version 2.1 (LGPLv2.1)
  • LGPLv2:
    'License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)',
  • LGPLv3 for the files in func_timeout, tests and the LICENSE file itself.

Memory leak using func_timeout .

def get_video_capture2(timeout=1):
        try:
            ReturnValue = func_timeout(timeout , cap .read)
            return ReturnValue
        except FunctionTimedOut:
            print("cap .read could not complete within {} seconds and was terminated".format(timeout))
        except Exception as e:
            print("Exception in cap.read() = {}".format(e))

Here is my python function where I use func_timeout.
without func_timeout memory leak is not found in this code.
I also try to free an object using del obj, but no changes were detected.

using del obj, python code


def get_video_capture2(timeout=1):
        global frame
        try:
            ReturnValue = func_timeout(timeout , cap .read)
            frame = ReturnValue
            del  ReturnValue
            return True
        except FunctionTimedOut:
            print("cap .read could not complete within {} seconds and was terminated".format(timeout))
        except Exception as e:
            print("Exception in cap.read() = {}".format(e))

so how can I free my memory ??

Way to set thread name?

In my app, I have a bunch of threads and tend to set a thread name then use the thread name in the logs. Is there a way to use func_timeout and set the name for the spawned thread (that could be timed-out, if that makes sense)?

In my current logs I see stuff like:

 Thread-39 (funcwrap)

as the thread id, which isn't as easy to look at as if I could give that spawned thread a name.

Threads have names that can be accessed/set via <thread>.name .. also via the constructor's name kwarg.

Thanks!

FunctionTimedOut exception cannot be raised with zero arguments

The function signature for func_timeout.exceptions.FunctionTimedOut is

def __init__(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None):

Indicating that all parameters are optional.

However, creating or throwing the exception with zero parameters raises an AttributeError exception

Minimal example

def throw_timeout_with_message():
    raise FunctionTimedOut('foo')

def throw_blank_timeout():
    raise FunctionTimedOut()

if __name__ == '__main__':
    # works correctly
    try:
        throw_timeout_with_message()
    except FunctionTimedOut as e:
        assert(isinstance(e, FunctionTimedOut))
        print('handled')

    # raises an uncaught error
    try:
        throw_blank_timeout()
    except FunctionTimedOut as e:
        assert(isinstance(e, FunctionTimedOut))
        print('handled')

Expected result of the second try/catch block:

> handled

Actual result of the second try/catch block:

Traceback (most recent call last):
  File ".../scratch_3.py", line 40, in <module>
    throw_blank_timeout()
  File ".../scratch_3.py", line 8, in throw_blank_timeout
    raise FunctionTimedOut()
  File "...\Python27\lib\site-packages\func_timeout\exceptions.py", line 36, in __init__
    msg = self.getMsg()
  File "...\Python27\lib\site-packages\func_timeout\exceptions.py", line 49, in getMsg
    return 'Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(self.timedOutFunction.__name__, repr(self.timedOutArgs), repr(self.timedOutKwargs), self.timedOutAfter)
AttributeError: 'NoneType' object has no attribute '__name__'

FunctionTimedOut Exception cannot be caught with Exception

func_timeout.exceptions.FunctionTimedOut does not inherit from Exception, making it impossible to catch in general purpose try/except blocks.

Python Version: 2.7
Windows 10

Minimal Example:

def catch_specific():
    try:
        raise FunctionTimedOut('foo')
    except FunctionTimedOut as e:
        print('handled ' + str(e))

def catch_general():
    try:
        raise FunctionTimedOut('bar')
    except Exception as e:
        print('handled ' + str(e))

if __name__ == '__main__':
    print(issubclass(FunctionTimedOut, Exception))
    catch_specific()
    catch_general()

Expected output when calling catch_general()

> handled bar

Actual output when calling catch_general()

Traceback (most recent call last):
  File "C:/Users/...", line 31, in <module>
    catch_general()
  File "C:/Users/.../scratch_3.py", line 21, in catch_general
    raise FunctionTimedOut('bar')
func_timeout.exceptions.FunctionTimedOut: bar

Why does this matter

While except Exception is generally a bad practice, there are various scenarios where it is the correct choice. The difference between except Exception:, and a naked except: or except BaseException: is that the latter two catch SystemExit, KeyboardInterrupt and a few other exceptions that should always be re-raised. Where except Exception is used for things like loggers, web servers, remote terminals, etc, where you want to log the exception and resume program execution.

func_timeout.dafunc.FunctionTimedOut{hash} exceptions

I use func_timeout with python 3.6.9,sometimes it will produce many func_timeout.dafunc.FunctionTimedOut{hash} exceptions.
image
image。Normally I can not catch this exception,In python 3.6.9, use sys.excepthook could get the error.
In python 3.8.6,sys.excepthook do not work.
image

And I don't know why this exception happened.

Failed to work in a loop.

Hi, I encountered a trouble when I use func_timeout in a loop.
environment:

  • python 3.8
  • func-timeout-4.3.5

Here is my code:
`
import func_timeout

@func_timeout.func_set_timeout(5)
def ask_choice():
print("yes or no:")
return input()

while True:
try:
s = ask_choice()
except func_timeout.exceptions.FunctionTimedOut as e:
s = 'DEFAULT!'
print(s)
`

Normally, it will simply respond what I input, or respond' DEFAULT!' if I didn't input in 5 second. But as long as I exceed time once, it won't response to my input anymore.
Could you please give me some suggestion? Thank you very much!

func_timeout is not working

Hi,

I am using a very simple code:

from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
import time

def test_time(a):
        print(f'start')
        time.sleep(8)
        print(f'end !!!')
        return a

try:
    y = func_timeout(5, test_time(),  args=(123))
    print(f'y is {y}')
except FunctionTimedOut:
    print("timeout")
except Exception as e:
    print(e)

I am trying to get a timeout error/exception but rater seems that the args are not getting passed to the function itself and getting an error as:

ERROR: test_time() missing 1 required positional argument: 'a'

if I hardcode the parameter too as:

from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
import time

def test_time(**a=123**):
        print(f'start')
        time.sleep(2)
        print(f'end !!!')
        return a

try:
    y = func_timeout(5, test_time(),  args=(123))
    print(f'y is {y}')
except FunctionTimedOut:
    print("timeout")
except Exception as e:
    print(e)

then I get an error as:

ERROR: int object argument after * must be an iterable, not int

could you pease suggest something for this so that I can get a timeout exception for a function call taking more than the desired time

Unable to handle user-defined exceptions occurring in thread_timeout

I have the following code (see comments):

class GoogleSheetTimeoutError(BaseException):
    # ... (not the interesting part)


def _handle_timeout():
    raise GoogleSheetTimeoutError(
        # ... (not the interesting part)
    )


def gsheets_api_thread_timeout(seconds=10):
    return thread_timeout(seconds, _handle_timeout)


class HttpError(Exception):
    def __init__(self, response: HTTPResponse):
        self.response = response
        self.content = _error_contents(response._body)  # Implementation not shown -- not interesting
        self.url = response.url

    @property
    def status_code(self):
        return self.response.status


@gsheets_api_thread_timeout(seconds=90)
def _execute_with_timeout(request: Callable[[], HTTPResponse]) -> Any:
    response: HTTPResponse = request()
    if response.status == 200:
        return response.json()
    else:
        # The error is raised here but is never caught in `perform_request(...)`
        raise HttpError(response)


@with_rate_limiting
def perform_request(
    request: Callable[[], HTTPResponse],
    retries: int = 5,
) -> Any:
    try:
        return _execute_with_timeout(request)

    except HttpError as e:
        if e.status_code == 503:
            # This error gets caught in my local docker container (so I know my
            # logic is not wrong, at least in a given environment configuration), but
            # not in production (AWS Fargate)

Is there something I'm missing?

I know my error handling is working perfectly fine in my local environment, and it's simply not working at all in my production environment.

Both environments are of course running with different hardware/resources, but both environments are running in docker (image python:3.10.8, with build argument --platform linux/amd64), with python 3.10.8 and func_timeout 4.3.5.

How to stop timeout task

I am trying to figure out the correct way to use this library, I use the following test code:

Python 2.7.5 (default, Sep 15 2016, 22:37:39) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> from func_timeout import func_set_timeout
>>> 
>>> @func_set_timeout(3)
... def test():
...     while True:
...         time.sleep(1)
...         print "test"
... 
>>> 
>>> test()
test
test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/site-packages/func_timeout/dafunc.py", line 185, in <lambda>
    return wraps(func)(lambda *args, **kwargs : func_timeout(defaultTimeout, func, args=args, kwargs=kwargs))
  File "/usr/lib/python2.7/site-packages/func_timeout/dafunc.py", line 101, in func_timeout
    raise FunctionTimedOut('', timeout, func, args, kwargs)
func_timeout.exceptions.FunctionTimedOut: Function test (args=()) (kwargs={}) timed out after 3.000000 seconds.

>>> test
test
test
test
test

KeyboardInterrupt
>>> test
test
test
test

After the func_timeout.exceptions.FunctionTimedOut, the test function is not terminated, how can i stop the function?

does not work with tkinter and socket and real-time print

I have a python code of 1000 LOC that I am happy to share.

It uses a client with GUI and a server. Upon user.__button_click(), the client sends a request to the server via socket and prints label text in real time on the program state. The server receives the request and then there is a back-and-forth between server and client, based on the kind of request. The server reacts on a request in the server.__serve_client() routine. The communication is with python socket.socket, .connect() and .listen(1) .

Naturally, I put the following python code around user.__button_click() and server.__serve_client() from above:

def run_function_with_timelimit(function,arguments,max_wait,default_value):
    try: return func_timeout.func_timeout(max_wait,function,args=arguments)
    except func_timeout.FunctionTimedOut: print("took too long")
    except Exception as e: print(f"error occured: {e}.")
    return default_value

Now nothing works anymore. Particularly, both the server and client repeatedly wait for 10 seconds and then print "took too long".

If you want to help me, point me to where I shall send you my code. Alternatively, I am happy for any instructions in this place on how to fix the error.

Library name typo

[ver 4.3.5]
There's a typo in the library's Name attribute: installation registers the name as "func-timeout" but the library is still called 'func_timeout'. See the screenshots below.

func_timeout

Using func_timeout with long running SQL

Hi,

First of all, thank you for this library, we like it very much it works great for most of my use case in AWS Lambda where we need to cleanly stop the Lambda function before it times out.


TL,DR: have you used this library to terminate a function with long running querries?


I am currently trying to combine this library with SQLAlchemy/psycopg to stop long running PostgreSQL transaction, but it doesn't work out of the box without some tweak.

First of all, func_timeout raise exception FuncTimeOut in both main thread and spawn thread. But SQLAlchemy/psycopg doesn't stop the transaction immediately (it seems that during transaction, SQLAlchemy silently handle any kind of exception raised except SQL exceptions), it waits for that transaction to be finished, and it could be very long. Most of the long running SQL in our cases ( several minutes) are bugged/race conditions or extreme case in rare condition and they affect other operations so they need to be killed.

So I derived something like this to stop long running transaction

# initialize the sqlalchemy session, to be used in func_with_long_sql
sql_session = ... 
try:
    ...
    response = func_timeout(timeout, func_with_long_sql, args, kwargs)
    ...
except FunctionTimedOut:
    # low level (psycopg), this uses PGCancel to abort the execution on PostgreSQL side
    sql_session.connection().connection.cancel()
    sql_session.rollback()
...

There is one problem with this solution is that there will be two exceptions inside spawn thread (FuncTimeOut exception and one SQL exception due to aborted query), and SQLAlchemy doesn't like it, it will say that one exception raises while handling another exception, the SQL connection/session will become stale.

As I need to use PGCancel to stop transaction, so I have to stop sending the other exception to spawn thread, and it works great so far.

My question is: should this solution (cancel an execution/rollback + disable of FuncTimeOut exception inside spawn thread) is the use case of func_timeout for SQL, or is there another way? I haven't found much on the net about this, maybe there is another better way?

We need to set timeout for each kind of operation, (and value in statement_timeout in PostgreSQL is set at big value for operation that really need long running queries)

Thank you,

License Issue

Hi,

We are planning to use the library
licensed under GNU Library General Public License v2
we are not doing any modifications in the source code of the library
GPL, or our application can be made proprietary
can you please more insights into this

Failing to timeout regex?

Howdy! Thanks for your work on this projec!

I'm honestly not sure if I've found a bug or if I'm misunderstanding the usage of the decorator. I'm trying to use func_set_timeout() to timeout some catastrophically backtracking regexes. (They scale of O(2^n), nasty little things) However, in my tests the decorator works just fine on a sleep function but doesn't catch the regex. In fact the process has to be killed from another shell.

Execution environment:

  • Centos 7 container
  • Python 3.7.5
  • Container running via Docker Desktop for macOS
import re
import time

import pytest

from func_timeout import func_set_timeout, FunctionTimedOut

@func_set_timeout(5)
def _sleep_method_func_timeout():
    time.sleep(10)

@func_set_timeout(5)
def _catastrophic_backtracking_regex():
    pattern = r"(\w+)\*([\w\s]+)*/$"
    re_compiled = re.compile(pattern)
    results = re_compiled.search('COPRO*HORIZON 2000                 HOR')
    print(results.groups())

# this passes
def test_func_timeout_decorator_sleep_func():
    with pytest.raises(FunctionTimedOut):
        _sleep_method_func_timeout()

# this does not pass and has to be killed externally
def test_func_timeout_decorater_regex():
    with pytest.raises(FunctionTimedOut):
        _catastrophic_backtracking_regex()

Terminal output:

[app@a456222c57ed src]$ pytest -v tests/test_timeout_handling.py 
================================================================= test session starts ==================================================================
platform linux -- Python 3.7.3, pytest-5.2.4, py-1.8.0, pluggy-0.13.0 -- /usr/local/pyenv/versions/3.7.3/bin/python3.7
cachedir: .pytest_cache
rootdir: /opt/app/src, inifile: pytest.ini
plugins: cov-2.8.1
collected 2 items                                                                                                                                      

tests/test_timeout_handling.py::test_func_timeout_decorator_sleep_func PASSED                                                                    [ 50%]
tests/test_timeout_handling.py::test_func_timeout_decorater_regex Killed

Is this related to #10? I don't think it is since that's really specific to Python2 and this is 3.7.5. Have I missed something in the README? Did I find a bug? Is my execution environment just a wacky snowflake?

Thanks again for your work!

Cannot use it in a nested manner

I'm using it under Python 3.8.4

from time import sleep

from func_timeout import func_set_timeout


@func_set_timeout(1)
def func_1(sec):
    print(f"in func 1, sleeping {sec} sec but will timeout in 1 sec")
    sleep(sec)


@func_set_timeout(1)
def func_2(sec):
    print(f"in func 2, sleeping {sec} sec but will timeout in 1 sec")
    sleep(sec)


@func_set_timeout(5)
def func():
    func_1(2)
    print("in main func")
    func_2(0.3)


if __name__ == "__main__":
    func()

This program would stop at func_1(2) silently
it seems the top level @func_set_timeout(5) swallows all the FunctionTimedOut and doesn't re-raise

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.