Last active
August 29, 2015 14:00
-
-
Save davidszotten/2b38858afc6e084d5630 to your computer and use it in GitHub Desktop.
Benchmarking argspec strategies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from __future__ import print_function # want same code for py2/py3 | |
| import inspect | |
| import sys | |
| has_signature = (sys.version_info[:2] >= (3, 3)) | |
| BAD_ARGS, GOOD_ARGS = (1, 2) | |
| def fun_good(arg1, arg2, arg3='default'): | |
| pass | |
| def fun_bad(arg1, arg2, arg3='default'): | |
| raise TypeError() | |
| # eval setup | |
| shadows = {} | |
| for fun in [fun_good, fun_bad]: | |
| argspec = inspect.getargspec(fun_good) | |
| signature = inspect.formatargspec(*argspec)[1:-1] # remove parens | |
| src = "lambda {}: None".format(signature) | |
| shadow = eval(src) | |
| shadows[fun] = shadow | |
| def with_eval(fun, *args, **kwargs): | |
| shadow = shadows[fun] | |
| try: | |
| fun(*args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| try: | |
| shadow(*args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| return BAD_ARGS | |
| def with_callargs(fun, *args, **kwargs): | |
| try: | |
| fun(*args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| try: | |
| inspect.getcallargs(fun_good, *args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| return BAD_ARGS | |
| def with_trace(fun, *args, **kwargs): | |
| try: | |
| fun(*args, **kwargs) | |
| except TypeError: | |
| if len(inspect.trace()) == 1: | |
| return BAD_ARGS | |
| return GOOD_ARGS | |
| if has_signature: | |
| # signature setup | |
| signatures = {} | |
| for fun in [fun_good, fun_bad]: | |
| signatures[fun] = inspect.signature(fun) | |
| def with_signature(fun, *args, **kwargs): | |
| try: | |
| fun(*args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| signature = signatures[fun] | |
| try: | |
| signature.bind(*args, **kwargs) | |
| return GOOD_ARGS | |
| except TypeError: | |
| return BAD_ARGS | |
| if __name__ == '__main__': | |
| import timeit | |
| number = 1000 | |
| extra_imports = "fun_good, fun_bad, GOOD_ARGS, BAD_ARGS" | |
| testers = ["eval", "callargs", "trace"] | |
| if has_signature: | |
| testers.append("signature") | |
| for tester in testers: | |
| test = """ | |
| assert tester(fun_good, 1, 2) == GOOD_ARGS | |
| assert tester(fun_good, 1) == BAD_ARGS | |
| assert tester(fun_bad, 1, 2) == GOOD_ARGS | |
| assert tester(fun_bad, 1) == BAD_ARGS | |
| """ | |
| result = timeit.timeit(test, | |
| setup="from __main__ import with_%s as tester, %s" % ( | |
| tester, extra_imports), | |
| number=number, | |
| ) | |
| adjust = max(map(len, testers)) | |
| print("%s: %s" % (tester.rjust(adjust), result)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment