metaprogramming - Name of a Python function in a stack trace -


in both python2 , python3, in stack trace __name__ of function not used, original name (the 1 specified after def) used instead.

consider example:

import traceback  def a():     return b()  def b():     return c()  def c():     print("\n".join(line.strip() line in traceback.format_stack()))  a.__name__ = 'a' b.__name__ = 'b' c.__name__ = 'c'  a(); 

the output is:

file "test.py", line 16, in <module>     a(); file "test.py", line 4, in     return b() file "test.py", line 7, in b     return c() file "test.py", line 10, in c     print("\n".join(line.strip() line in traceback.format_stack())) 

why so? how change name used in stack trace? __name__ attribute used then?

so, every function has 3 things can considered being name of function:

the original name of code block

it's stored in f.__code__.co_name (where f function object). if use def orig_name create function, orig_name name. lambas it's <lambda>.

this attribute readonly , can't changed. way create function custom name in runtime i'm aware of exec:

exec("""def {name}():   print '{name}' """.format(name='any')) in globals()  any()  # prints 'any' 

(there more low-level way this mentioned in comment question.)

the immutability of co_name makes sense: can sure name see in debugger (or stack trace) same see in source code (along filename , line number).

the __name__ attribute of function object

it's aliased func_name.

you can modify (orig_name.__name__ = 'updated name') , surely on daily basis: @functools.wraps copies __name__ of decorated function new one.

__name__ used tools pydoc, that's why need @functools.wraps: don't see technical details of every decorator in documentation. @ example:

from functools import wraps  def decorator1(f):     def decorated(*args, **kwargs):         print 'start1'         f(*args, **kwargs)     return decorated  def decorator2(f):     @wraps(f)     def decorated(*args, **kwargs):         print 'start2'         f(*args, **kwargs)     return decorated  @decorator1 def test1():     print 'test1'  @decorator2 def test2():     print 'test2' 

here pydoc output:

functions     decorator1(f)      decorator2(f)      test1 = decorated(*args, **kwargs)      test2(*args, **kwargs) 

with wraps there no sign of decorated in documentation.

name of reference

one more thing can called function name (though hardly is) name of variable or attribute reference function stored.

if create function def name, name attribute added current scope. in case of lambda should assign result variable: name = lambda: none.

obviously can create more 1 reference same function , references can have different names.


the way 3 things connected each other def foo statement creates function object both __name__ , __code__.co_name equal foo , assign foo attribute of current scope. not bound in way , can different each other:

import traceback                               def make_function():                              def orig_name():                                  """docstring here                             """                                           traceback.print_stack()                   return orig_name                           globals()['name_in_module'] = make_function() name_in_module.__name__ = 'updated name'       name_in_module()                              

output:

  file "my.py", line 13, in <module>     name_in_module()   file "my.py", line 7, in orig_name     traceback.print_stack() 

pydoc:

functions     make_function()      name_in_module = updated name()         docstring here 

i thank other people comments , answers, helped me organize thoughts , knowledge.


Comments

Popular posts from this blog

account - Script error login visual studio DefaultLogin_PCore.js -

xcode - CocoaPod Storyboard error: -