func-timeout


Namefunc-timeout JSON
Version 4.3.5 PyPI version JSON
download
home_pagehttps://github.com/kata198/func_timeout
SummaryPython module which allows you to specify timeouts when calling any existing function. Also provides support for stoppable-threads
upload_time2019-08-19 21:32:07
maintainerTim Savannah
docs_urlhttps://pythonhosted.org/func-timeout/
authorTim Savannah
requires_python
licenseLGPLv2
keywords function timeout call terminate runtime max seconds after execution
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            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
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/kata198/func_timeout",
    "name": "func-timeout",
    "maintainer": "Tim Savannah",
    "docs_url": "https://pythonhosted.org/func-timeout/",
    "requires_python": "",
    "maintainer_email": "kata198@gmail.com",
    "keywords": "function,timeout,call,terminate,runtime,max,seconds,after,execution",
    "author": "Tim Savannah",
    "author_email": "kata198@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/b3/0d/bf0567477f7281d9a3926c582bfef21bff7498fc0ffd3e9de21811896a0b/func_timeout-4.3.5.tar.gz",
    "platform": "",
    "description": "func\\_timeout\n=============\n\nPython module to support running any existing function with a given timeout.\n\n\nFunction Timeout\n================\n\n\nfunc\\_timeout\n-------------\n\nThis 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.\n\n\tdef func\\_timeout(timeout, func, args=(), kwargs=None):\n\n\t\t'''\n\n\t\t\tfunc\\_timeout \\- Runs the given function for up to #timeout# seconds.\n\n\t\t\tRaises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut\n\n\t\t\t@param timeout <float> \\- Maximum number of seconds to run #func# before terminating\n\n\t\t\t@param func <function> \\- The function to call\n\n\t\t\t@param args    <tuple> \\- Any ordered arguments to pass to the function\n\n\t\t\t@param kwargs  <dict/None> \\- Keyword arguments to pass to the function.\n\n\t\t\t@raises \\- FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised\n\n\t\t\t@return \\- The return value that #func# gives\n\n\t\t'''\n\n\n**Example**\n\n\nSo, 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:\n\n\n\tfrom func\\_timeout import func\\_timeout, FunctionTimedOut\n\n\t...\n\n\ttry:\n\n\t\tdoitReturnValue = func\\_timeout(5, doit, args=('arg1', 'arg2'))\n\n\texcept FunctionTimedOut:\n\n\t\tprint ( \"doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.\\\\n\")\n\n\texcept Exception as e:\n\n\t\t# Handle any exceptions that doit might raise here\n\n\n\nfunc\\_set\\_timeout\n------------------\n\n\nThis is a decorator you can use on functions to apply func\\_timeout.\n\nTakes two arguments, \"timeout\" and \"allowOverride\"\n\nIf \"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.\n\n\nThe \"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.\n\n\n**Example:**\n\n\t@func\\_set\\_timeout(2.5)\n\n\tdef myFunction(self, arg1, arg2):\n\n\t\t...\n\n\nFunctionTimedOut\n----------------\n\nException raised if the function times out.\n\n\nHas a \"retry\" method which takes the following arguments:\n\n\t\\* No argument \\- Retry same args, same function, same timeout\n\n\t\\* Number argument \\- Retry same args, same function, provided timeout\n\n\t\\* None \\- Retry same args, same function, no timeout\n\n\nHow it works\n------------\n\nfunc\\_timeout will run the specified function in a thread with the specified arguments until it returns, raises an exception, or the timeout is exceeded.\n\nIf there is a return or an exception raised, it will be returned/raised as normal.\n\nIf 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.\n\n\nStoppableThread\n===============\n\nStoppableThread 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.\n\nThe 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).\n\n\nUsing StoppableThread\n---------------------\n\nYou can use StoppableThread one of two ways:\n\n**As a Parent Class**\n\n\nYour thread can extend func\\_timeout.StoppableThread\\.StoppableThread and implement the \"run\" method, same as a normal thread.\n\n\n\tfrom func\\_timeout.StoppableThread import StoppableThread\n\n\tclass MyThread(StoppableThread):\n\n\t\tdef run(self):\n\t\t\t\n\t\t\t# Code here\n\n\t\t\treturn\n\n\nThen, you can create and start this thread like:\n\n\tmyThread = MyThread()\n\n\t# Uncomment next line to start thread in \"daemon mode\" \\-\\- i.e. will terminate/join automatically upon main thread exit\n\n\t#myThread.daemon = True\n\n\tmyThread.start()\n\n\nThen, at any time during the thread's execution, you can call \\.stop( StopExceptionType ) to stop it ( more in \"Stopping a Thread\" below\n\n**Direct Thread To Execute A Function**\n\nAlternatively, you can instantiate StoppableThread directly and pass the \"target\", \"args\", and \"kwargs\" arguments to the constructor\n\n\tmyThread = StoppableThread( target=myFunction, args=('ordered', 'args', 'here'), kwargs={ 'keyword args' : 'here' } )\n\n\t# Uncomment next line to start thread in \"daemon mode\" \\-\\- i.e. will terminate/join automatically upon main thread exit\n\n\t#myThread.daemon = True\n\n\tmyThread.start()\n\n\nThis 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.\n\n\nStopping a Thread\n-----------------\n\n\nThe *StoppableThread* class (you must extend this for your thread) adds a function, *stop*, which can be called to stop the thread.\n\n\n\tdef stop(self, exception, raiseEvery=2.0):\n\n\t\t'''\n\n\t\t\tStops the thread by raising a given exception.\n\n\t\t\t@param exception <Exception type> \\- Exception to throw. Likely, you want to use something\n\n\t\t\t  that inherits from BaseException (so except Exception as e: continue; isn't a problem)\n\n\t\t\t  This should be a class/type, NOT an instance, i.e.  MyExceptionType   not  MyExceptionType()\n\n\n\t\t\t@param raiseEvery <float> Default 2.0 \\- We will keep raising this exception every #raiseEvery seconds,\n\n\t\t\t\tuntil the thread terminates.\n\n\t\t\t\tIf your code traps a specific exception type, this will allow you #raiseEvery seconds to cleanup before exit.\n\n\t\t\t\tIf you're calling third\\-party code you can't control, which catches BaseException, set this to a low number\n\t\t\t\t \n\t\t\t\t  to break out of their exception handler.\n\n\n\t\t\t @return <None>\n\n\t\t'''\n\n\nThe \"exception\" param must be a type, and it must be instantiable with no arguments (i.e. MyExceptionType() must create the object).\n\nConsider using a custom exception type which extends BaseException, which you can then use to do basic cleanup ( flush any open files, etc. ).\n\nThe 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 ).\n\n\n**Notes on Exception Type**\n\nIt is recommended that you create an exception that extends BaseException instead of Exception, otherwise code like this will never stop:\n\n\twhile True:\n\n\t\ttry:\n\n\t\t\tdoSomething()\n\n\t\texcept Exception as e:\n\n\t\t\tcontinue\n\nIf 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.\n\n\n\nYou may want to consider using singleton types with fixed error messages, so that tracebacks, etc. log that the call timed out.\n\nFor example:\n\n\tclass ServerShutdownExceptionType(BaseException):\n\n\t\tdef \\_\\_init\\_\\_(self, \\*args, \\*\\*kwargs):\n\n\t\t\tBaseException.\\_\\_init\\_\\_(self, 'Server is shutting down')\n\n\nThis will force 'Server is shutting down' as the message held by this exception.\n\n\n\nPydoc\n=====\n\nFind the latest pydoc at http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=4.3.5 .\n\n\nSupport\n=======\n\nI've tested func\\_timeout with python 2.7, 3.4, 3.5, 3.6, 3.7. It should work on other versions as well.\n\nWorks on windows, linux/unix, cygwin, mac\n\nChangeLog can be found at https://raw.githubusercontent.com/kata198/func_timeout/master/ChangeLog \n\nPydoc can be found at: http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=1",
    "bugtrack_url": null,
    "license": "LGPLv2",
    "summary": "Python module which allows you to specify timeouts when calling any existing function. Also provides support for stoppable-threads",
    "version": "4.3.5",
    "project_urls": {
        "Homepage": "https://github.com/kata198/func_timeout"
    },
    "split_keywords": [
        "function",
        "timeout",
        "call",
        "terminate",
        "runtime",
        "max",
        "seconds",
        "after",
        "execution"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b30dbf0567477f7281d9a3926c582bfef21bff7498fc0ffd3e9de21811896a0b",
                "md5": "3535d4e00d54e36757ba7c65f20e4c91",
                "sha256": "74cd3c428ec94f4edfba81f9b2f14904846d5ffccc27c92433b8b5939b5575dd"
            },
            "downloads": -1,
            "filename": "func_timeout-4.3.5.tar.gz",
            "has_sig": false,
            "md5_digest": "3535d4e00d54e36757ba7c65f20e4c91",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 44264,
            "upload_time": "2019-08-19T21:32:07",
            "upload_time_iso_8601": "2019-08-19T21:32:07.430628Z",
            "url": "https://files.pythonhosted.org/packages/b3/0d/bf0567477f7281d9a3926c582bfef21bff7498fc0ffd3e9de21811896a0b/func_timeout-4.3.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2019-08-19 21:32:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "kata198",
    "github_project": "func_timeout",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "func-timeout"
}
        
Elapsed time: 3.79996s