New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update module attribute on namedtuple methods for introspection. #77561
Comments
Python 3.7 made several performance improvements to the namedtuple class as part of https://bugs.python.org/issue28638 Prior to the implementation of bpo-28638, the __module__ attribute for a namedtuple's methods (e.g. _asdict) would return the value 'namedtuple_%s' % typename (e.g. namedtuple_Point). Due to the optimizations made, the __module__ attribute for a namedtuple's methods now returns 'collections'. The proposed change as part of this issue is to report the more accurate derived module name for the namedtuple methods. Updating the __module__ attribute should help debug and introspection tools more accurately report the details of executing calls (in profilers for example). Example from Python 3.6:
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ('x', 'y'))
>>> p1 = Point(1,2)
>>> p1._asdict.__module__
'namedtuple_Point'
Example from Python 3.7.0b3:
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ('x', 'y'))
>>> p1 = Point(1,2)
>>> p1._asdict.__module__
'collections'
Desired behavior:
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ('x', 'y'))
>>> p1 = Point(1,2)
>>> p1._asdict.__module__
'__main__' |
Attached is a proposed change. |
Am not sure I can see any value in pushing the __module__ attribute down into the methods and think it is reasonable for them to report their origin as being in the collections module. |
I see that as a good fix, obviously Point definition belongs to __main__ in the sample, like would any other subclass defined there eg if "some" class is defined in awe.py module : >>> import awe
>>> class my(awe.some):pass
...
>>> my.__module__
'__main__' |
ISTM collections is the correct module reference because that is where the code is actually defined. A debugging tool should look there instead of in the calling code. This is the way other tools work in Python as well: >>> from collections.abc import Set
>>> class S(Set):
def __init__(self): pass
def __iter__(self): yield 0
def __len__(self): return 0
def __contains__(self, key): return False
>>> S.__or__.__module__
'collections.abc'
>>> from dataclasses import make_dataclass
>>> P = make_dataclass('P', ['x', 'y'])
>>> P.__repr__.__module__
'dataclasses' Likewise, the various tools that use closures used to report the module where the closure was defined rather than the module of the caller's code (see functools.cmp_to_key or functools.lru_cache). I say "used to" because the pure Python code is now supplanted by C equivalents where the __module__ attribute__ is appropriately set to None: # Running from PyPy
>>>> from functools import cmp_to_key
>>>> c = cmp_to_key(lambda x, y: 0)
>>>> c.__init__.__module__
'_functools' The Data Model section of the Language Reference defines __module__ as follows, "__module__: The name of the module the function was defined in, or None if unavailable." In the prior version of namedtuple(), the function was defined in a virtual module (an execed string). Now, that the methods are defined in a real module, the __module__ attribute should name that real module. |
That explanation makes sense to me. Thanks for taking the time to look into this! |
Indeed thanks for the deep explanation. It seems that not finding im_self anymore (not even in the dunder clutter), i've mistaken '.__self__.__module__' with '.__module__'. How joyfull to learn anew to trace a caller id, and sorry for the noise (again). |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: