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

Posted on

Question :

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

What I’m trying to do would look like this in the command line:

>>> import mymodule
>>> names = dir(mymodule)

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__)

Answer #1:

Just use globals()

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).

http://docs.python.org/library/functions.html#globals

Answered By: guillermooo

Answer #2:

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__])
Answered By: Maciej Pasternacki

Answer #3:

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 == '<module>':
      if stack_frame.f_code.co_filename != '<stdin>':
        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

Pros:

  • 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:pythonx8637libsite-packagesxonshpytest_plugin.py 58
*** pytest_runtest_call c:pythonx8637libsite-packages_pytestrunner.py 125
*** _multicall c:pythonx8637libsite-packagespluggycallers.py 187
*** <lambda> c:pythonx8637libsite-packagespluggymanager.py 86
*** _hookexec c:pythonx8637libsite-packagespluggymanager.py 92
*** __call__ c:pythonx8637libsite-packagespluggyhooks.py 286
*** <lambda> c:pythonx8637libsite-packages_pytestrunner.py 201
*** from_call c:pythonx8637libsite-packages_pytestrunner.py 229
*** call_runtest_hook c:pythonx8637libsite-packages_pytestrunner.py 201
*** call_and_report c:pythonx8637libsite-packages_pytestrunner.py 176
*** runtestprotocol c:pythonx8637libsite-packages_pytestrunner.py 95
*** pytest_runtest_protocol c:pythonx8637libsite-packages_pytestrunner.py 80
*** _multicall c:pythonx8637libsite-packagespluggycallers.py 187
*** <lambda> c:pythonx8637libsite-packagespluggymanager.py 86
*** _hookexec c:pythonx8637libsite-packagespluggymanager.py 92
*** __call__ c:pythonx8637libsite-packagespluggyhooks.py 286
*** pytest_runtestloop c:pythonx8637libsite-packages_pytestmain.py 258
*** _multicall c:pythonx8637libsite-packagespluggycallers.py 187
*** <lambda> c:pythonx8637libsite-packagespluggymanager.py 86
*** _hookexec c:pythonx8637libsite-packagespluggymanager.py 92
*** __call__ c:pythonx8637libsite-packagespluggyhooks.py 286
*** _main c:pythonx8637libsite-packages_pytestmain.py 237
*** wrap_session c:pythonx8637libsite-packages_pytestmain.py 193
*** pytest_cmdline_main c:pythonx8637libsite-packages_pytestmain.py 230
*** _multicall c:pythonx8637libsite-packagespluggycallers.py 187
*** <lambda> c:pythonx8637libsite-packagespluggymanager.py 86
*** _hookexec c:pythonx8637libsite-packagespluggymanager.py 92
*** __call__ c:pythonx8637libsite-packagespluggyhooks.py 286
*** main c:pythonx8637libsite-packages_pytestconfig__init__.py 90
*** <module> c:Pythonx8637Scriptspytest.exe__main__.py 7
  • Can handle python piped or interactive session.

Cons:

  • 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

I have an extension to the python:
How to import a module given the full path?

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 = '<module>'):
  ...

You have to just initialize the extension properly:

# portable import to the global space
sys.path.append(<path-to-tacklelib-module-directory>)
import tacklelib as tkl

tkl.tkl_init(tkl, global_config = {'log_import_module':os.environ.get('TACKLELIB_LOG_IMPORT_MODULE')})

# 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 ...
Answered By: jamesls

Leave a Reply

Your email address will not be published. Required fields are marked *