Sleeping and invoking a task in Python 2.X and Python 3.X
You can use next() function in both Python 2.6+ and 3.x. If you need to support Python &lt; 2.6, you can have your own next() function. You can, for instance, check if referring to next throws a NameError and define it if it does:

try:
    next
except NameError:
    _sentinel = object()
    def next(it, default=_sentinel):
        try:
            return it.next()
        except StopIteration:
            if default is _sentinel:
                raise
            return default


Even though getargspec() got deprecated since 3.0, it still can be used and imported. In this case, you can import getfullargspec() and catch the ImportError:

try:
    from inspect import getfullargspec as get_args  # Python 3
except ImportError:
    from inspect import getargspec as get_args  # Python 2


Taking these both points into account, the code would look like:

time.sleep(next(iterator))
if len(arguments) &gt;= len(get_args(task).args):
    task(*arguments)
else:
    print("ERROR: There is a mismatch between the number of"
          " arguments provided in `arguments` and the ones"
          " needed by the task function.")


As far as generally supporting multiple Python versions in a single codebase, six is a must use package.



Also note that instead of using inspect to pre-validate the number of arguments, you can follow the EAFP approach, call the function and handle a TypeError:

&gt;&gt;&gt; f = lambda x, y: 'test'
&gt;&gt;&gt; f(1,2,3)
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: &lt;lambda&gt;() takes exactly 2 arguments (3 given)