Skip to content

Instantly share code, notes, and snippets.

@davidszotten
Last active August 29, 2015 14:00
Show Gist options
  • Select an option

  • Save davidszotten/2b38858afc6e084d5630 to your computer and use it in GitHub Desktop.

Select an option

Save davidszotten/2b38858afc6e084d5630 to your computer and use it in GitHub Desktop.
Benchmarking argspec strategies
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