Initial Release

This commit is contained in:
Tim Savannah 2016-03-14 22:37:03 -04:00
parent 37a15a64c3
commit 9104d8ca62
7 changed files with 393 additions and 2 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.pyc
*.pyo
*~
build/
dist/
*.egg-info/

7
MANIFEST.in Normal file
View File

@ -0,0 +1,7 @@
include setup.py
include LICENSE
include README.md
include README.rst
include MANIFEST.in
recursive-include func_timeout *.py
recursive-include doc *.html

View File

@ -1,2 +1,55 @@
# func_timeout
Python module to support running any existing function with a given timeout
# func\_timeout
Python module to support running any existing function with a given timeout.
Package Includes
----------------
**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
'''
**FunctionTimedOut**
Exception raised if the function times out
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
Support
-------
I've tested func\_timeout with python 2.7 and python 3.5.

74
README.rst Normal file
View File

@ -0,0 +1,74 @@
func_timeout
=============
Python module to support running any existing function with a given timeout.
Package Includes
----------------
**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
'''
**FunctionTimedOut**
Exception raised if the function times out
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
Support
-------
I've tested func_timeout with python 2.7 and python 3.5.

116
doc/func_timeout.html Normal file
View File

@ -0,0 +1,116 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: package func_timeout</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>func_timeout</strong></big></big> (version 1.0.0)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a></font></td></tr></table>
<p><tt>Copyright&nbsp;(c)&nbsp;2016&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br>
&nbsp;<br>
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br>
LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="builtins.html#Exception">builtins.Exception</a>(<a href="builtins.html#BaseException">builtins.BaseException</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="func_timeout.html#FunctionTimedOut">FunctionTimedOut</a>
</font></dt></dl>
</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="FunctionTimedOut">class <strong>FunctionTimedOut</strong></a>(<a href="builtins.html#Exception">builtins.Exception</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt>Common&nbsp;base&nbsp;class&nbsp;for&nbsp;all&nbsp;non-exit&nbsp;exceptions.<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="func_timeout.html#FunctionTimedOut">FunctionTimedOut</a></dd>
<dd><a href="builtins.html#Exception">builtins.Exception</a></dd>
<dd><a href="builtins.html#BaseException">builtins.BaseException</a></dd>
<dd><a href="builtins.html#object">builtins.object</a></dd>
</dl>
<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="builtins.html#Exception">builtins.Exception</a>:<br>
<dl><dt><a name="FunctionTimedOut-__init__"><strong>__init__</strong></a>(self, /, *args, **kwargs)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__new__"><strong>__new__</strong></a>(*args, **kwargs)<font color="#909090"><font face="helvetica, arial"> from <a href="builtins.html#type">builtins.type</a></font></font></dt><dd><tt>Create&nbsp;and&nbsp;return&nbsp;a&nbsp;new&nbsp;object.&nbsp;&nbsp;See&nbsp;help(type)&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<hr>
Methods inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><a name="FunctionTimedOut-__delattr__"><strong>__delattr__</strong></a>(self, name, /)</dt><dd><tt>Implement&nbsp;delattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__getattribute__"><strong>__getattribute__</strong></a>(self, name, /)</dt><dd><tt>Return&nbsp;getattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__reduce__"><strong>__reduce__</strong></a>(...)</dt><dd><tt>helper&nbsp;for&nbsp;pickle</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__repr__"><strong>__repr__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;repr(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__setattr__"><strong>__setattr__</strong></a>(self, name, value, /)</dt><dd><tt>Implement&nbsp;setattr(self,&nbsp;name,&nbsp;value).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
<dl><dt><a name="FunctionTimedOut-__str__"><strong>__str__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;str(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-with_traceback"><strong>with_traceback</strong></a>(...)</dt><dd><tt><a href="builtins.html#Exception">Exception</a>.<a href="#FunctionTimedOut-with_traceback">with_traceback</a>(tb)&nbsp;--<br>
set&nbsp;self.<strong>__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;self.</tt></dd></dl>
<hr>
Data descriptors inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><strong>__cause__</strong></dt>
<dd><tt>exception&nbsp;cause</tt></dd>
</dl>
<dl><dt><strong>__context__</strong></dt>
<dd><tt>exception&nbsp;context</tt></dd>
</dl>
<dl><dt><strong>__dict__</strong></dt>
</dl>
<dl><dt><strong>__suppress_context__</strong></dt>
</dl>
<dl><dt><strong>__traceback__</strong></dt>
</dl>
<dl><dt><strong>args</strong></dt>
</dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#eeaa77">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-func_timeout"><strong>func_timeout</strong></a>(timeout, func, args=(), kwargs=None)</dt></dl>
</td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>__all__</strong> = ('func_timeout', 'FunctionTimedOut')<br>
<strong>__version_tuple__</strong> = (1, 0, 0)</td></tr></table>
</body></html>

79
func_timeout/__init__.py Normal file
View File

@ -0,0 +1,79 @@
'''
Copyright (c) 2016 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import sys
import threading
import time
__version__ = '1.0.0'
__version_tuple__ = (1, 0, 0)
__all__ = ('func_timeout', 'FunctionTimedOut')
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
'''
if not kwargs:
kwargs = {}
if not args:
args = ()
ret = []
exception = []
def funcwrap(args2, kwargs2):
sys.stdout.write('Args2: %s\nkwargs2: %s\n' %(str(args2), str(kwargs2)))
try:
ret.append( func(*args2, **kwargs2) )
except Exception as e:
exception.append(e)
thread = threading.Thread(target=funcwrap, args=(args, kwargs))
thread.start()
thread.join(timeout)
if thread.isAlive():
doRaiseCantStop = False
thread.isDaemon = True
try:
if hasattr(thread, '_tstate_lock'):
# 3.5
thread._tstate_lock.release()
elif hasattr(thread, '_Thread__stop'):
# 2.7
thread._Thread__stop()
else:
doRaiseCantStop = True
except:
pass
if doRaiseCantStop is True:
raise NotImplementedError('function timeouts not supported on this system.\n')
if exception:
raise exception[0]
if ret:
return ret[0]
raise FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout))
class FunctionTimedOut(Exception):
pass

56
setup.py Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env python
'''
Copyright (c) 2016 Tim Savannah All Rights Reserved.
This software is licensed under the terms of the Lesser GNU General Public License Version 2.1 (LGPLv2.1)
You should have received a copy of this with the source distribution as LICENSE,
otherwise the most up to date license can be found at
https://github.com/kata198/func_timeout/LICENSE
'''
import os
import sys
from setuptools import setup
if __name__ == '__main__':
dirName = os.path.dirname(__file__)
if dirName and os.getcwd() != dirName:
os.chdir(dirName)
summary = 'Python module which allows you to specify timeouts when calling any existing function'
try:
with open('README.rst', 'rt') as f:
long_description = f.read()
except Exception as e:
sys.stderr.write('Error reading from README.rst: %s\n' %(str(e),))
log_description = summary
setup(name='func_timeout',
version='1.0.0',
packages=['func_timeout']
author='Tim Savannah',
author_email='kata198@gmail.com',
maintainer='Tim Savannah',
url='https://github.com/kata198/func_timeout',
maintainer_email='kata198@gmail.com',
description=summary,
long_description=long_description,
license='LGPLv2',
keywords=['function', 'timeout', 'call', 'terminate', 'runtime', 'max', 'seconds', 'after', 'execution']
classifiers=['Development Status :: 5 - Production/Stable'
'Programming Language :: Python',
'License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)'
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Software Development :: Libraries :: Python Modules'
]
)