I'm writing a program that needs to be compatible for both Python 2.X and Python 3.X. My problem is that, because of the differences between these two versions, I'm duplicating code.try:        ### Python 2.X part        time.sleep(iterator.next())        if len(arguments) >= len(inspect.getargspec(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.)except AttributeError:        ### Python 3.X part        time.sleep(next(iterator))        if len(arguments) >= len(inspect.getfullargspec(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.)It can be seen that both versions only differ in the usage of next(), inspect.getargspec() and inspect.getfullargspec(), while the other logic remains the same. Is there any way to optimize the execution of the tasks, in tasks(*arguments), and the printing of the error messages, so that I don't have to repeat the same code? This is just sample working code, but I mean my question in a more broader and general case.
Sleeping and invoking a task in Python 2.X and Python 3.X
python;iterator;reflection;variadic
You can use next() function in both Python 2.6+ and 3.x. If you need to support Python < 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:    nextexcept NameError:    _sentinel = object()    def next(it, default=_sentinel):        try:            return it.next()        except StopIteration:            if default is _sentinel:                raise            return defaultEven 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 3except ImportError:    from inspect import getargspec as get_args  # Python 2Taking these both points into account, the code would look like:time.sleep(next(iterator))if len(arguments) >= 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:>>> f = lambda x, y: 'test'>>> f(1,2,3)Traceback (most recent call last):  File <stdin>, line 1, in <module>TypeError: <lambda>() takes exactly 2 arguments (3 given)