Python getattr this module

How to get a reference to current module’s attributes in Python

How can I get a reference to all the names defined in mymodule from within mymodule itself? Something like this:

# mymodule.py names = dir(__thismodule__) 

3 Answers 3

As previously mentioned, globals gives you a dictionary as opposed to dir() which gives you a list of the names defined in the module. The way I typically see this done is like this:

import sys dir(sys.modules[__name__]) 

I was going to add a comment that this wouldn’t work for the ‘main‘ module (which is what the module run at the terminal is called) because that does not seem to be listed in sys.modules — but it does indeed work 🙂

Excellent! This just allowed me to use the current module’s docstring as a usage message — sys.modules[__name__].__doc__ .

And to get super hacky. operators.attrgetter(‘module.attribute’)(sys.modules[__name__]) — you know, if you do crazy things people tell you not to do like dynamically import packages from strings and then monkey patch those while not being within a class or anything.

For anyone reading comment by george: sys.modules[__name__].__doc__ == __doc__ as this is defined in the current namespace. Fetching the module object to access its own attributes is therefore not necessary.

globals() — Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).

You may try getting caller’s globals from the traceback module (docs.python.org/library/traceback.html), but this is getting into dark magic territory. I don’t know what you’re trying to do, but you may want to rethink your design if you need that.

Читайте также:  Pyd файлы python чем открыть

A classic case of «I need X (to get Y done) -> You don’t need X you need Z». I do need X though! No offense, I just find this amusing, and the most voted answer gives me the answer I need 🙂

Important to note that the globals() can return wrong result as it depends on the context where being called. For example, if make a call from a class function, then it will return the global context linked to the class, not the current module context, which is significally different thing. Even if make a call from a free function it can return a different module global context, dependent on how the function has been imported.

It might be late to answer, but I didn’t found the correct answer for myself. The most closest and precise solution (faster than inspect.stack() ) in the python 3.7.x :

# search for first module in the stack stack_frame = inspect.currentframe() while stack_frame: print('***', stack_frame.f_code.co_name, stack_frame.f_code.co_filename, stack_frame.f_lineno) if stack_frame.f_code.co_name == '': if stack_frame.f_code.co_filename != '': caller_module = inspect.getmodule(stack_frame) else: # piped or interactive import caller_module = sys.modules['__main__'] if not caller_module is None: #. do something here . break stack_frame = stack_frame.f_back 
  • Preciser than globals() method.
  • Does not depend on the stack intermediate frames, which can be added for example, via hooking or by the 3dparty tools like pytest :
*** foo . .. *** boo . .. *** runtest c:\python\x86\37\lib\site-packages\xonsh\pytest_plugin.py 58 *** pytest_runtest_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 125 *** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187 *** c:\python\x86\37\lib\site-packages\pluggy\manager.py 86 *** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92 *** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286 *** c:\python\x86\37\lib\site-packages\_pytest\runner.py 201 *** from_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 229 *** call_runtest_hook c:\python\x86\37\lib\site-packages\_pytest\runner.py 201 *** call_and_report c:\python\x86\37\lib\site-packages\_pytest\runner.py 176 *** runtestprotocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 95 *** pytest_runtest_protocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 80 *** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187 *** c:\python\x86\37\lib\site-packages\pluggy\manager.py 86 *** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92 *** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286 *** pytest_runtestloop c:\python\x86\37\lib\site-packages\_pytest\main.py 258 *** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187 *** c:\python\x86\37\lib\site-packages\pluggy\manager.py 86 *** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92 *** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286 *** _main c:\python\x86\37\lib\site-packages\_pytest\main.py 237 *** wrap_session c:\python\x86\37\lib\site-packages\_pytest\main.py 193 *** pytest_cmdline_main c:\python\x86\37\lib\site-packages\_pytest\main.py 230 *** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187 *** c:\python\x86\37\lib\site-packages\pluggy\manager.py 86 *** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92 *** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286 *** main c:\python\x86\37\lib\site-packages\_pytest\config\__init__.py 90 *** c:\Python\x86\37\Scripts\pytest.exe\__main__.py 7 
  • A kind of much precise and can return modules registered in an executable like for the pytest.exe which might not what you want.
  • inspect.getmodule still may return None on valid modules depending on hooking
Читайте также:  Основы сетевого программирования java

The extension having wrapper functions for that case:

def tkl_get_stack_frame_module_by_offset(skip_stack_frames = 0, use_last_frame_on_out_of_stack = False): . def tkl_get_stack_frame_module_by_name(name = ''): . 

You have to just initialize the extension properly:

# portable import to the global space sys.path.append() import tacklelib as tkl tkl.tkl_init(tkl, global_config = ) # cleanup del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist sys.path.pop() # use `tkl_*` functions directly from here . 

Источник

Оцените статью