I would like to be able to dynamically retrieve the current executing module or class name from within an imported module. Here is some code:
foo.py:
Using __file__
alone gives you a relative path for the main module and an absolute path for imported modules. Being aware this we can get the module file constantly either way with a little help from our os.path
tools.
For filename only use __file__.split(os.path.sep)[-1]
.
For complete path use os.path.abspath(__file__)
.
Demo:
/tmp $ cat f.py
from pprint import pprint
import os
import sys
pprint({
'sys.modules[__name__]': sys.modules[__name__],
'__file__': __file__,
'__file__.split(os.path.sep)[-1]': __file__.split(os.path.sep)[-1],
'os.path.abspath(__file__)': os.path.abspath(__file__),
})
/tmp $ cat i.py
import f
Results:
## on *Nix ##
/tmp $ python3 f.py
{'sys.modules[__name__]': <module '__main__' from 'f.py'>,
'__file__': 'f.py',
'__file__.split(os.path.sep)[-1]': 'f.py',
'os.path.abspath(__file__)': '/tmp/f.py'}
/tmp $ python3 i.py
{'sys.modules[__name__]': <module 'f' from '/tmp/f.pyc'>,
'__file__': '/tmp/f.pyc',
'__file__.split(os.path.sep)[-1]': 'f.pyc',
'os.path.abspath(__file__)': '/tmp/f.pyc'}
## on Windows ##
PS C:\tmp> python3.exe f.py
{'sys.modules[__name__]': <module '__main__' from 'f.py'>,
'__file__': 'f.py',
'__file__.split(os.path.sep)[-1]': 'f.py',
'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'}
PS C:\tmp> python3.exe i.py
{'sys.modules[__name__]': <module 'f' from 'C:\\tools\\cygwin\\tmp\\f.py'>,
'__file__': 'C:\\tools\\cygwin\\tmp\\f.py',
'__file__.split(os.path.sep)[-1]': 'f.py',
'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'}
If you want to strip the '.py' off the end, you can do that easily. (But don't forget that you may run a '.pyc' instead.)
If you want only the name of the file:
file_name = __file__.split("/")[len(__file__.split("/"))-1]
I don't believe that's possible since that's out of foo
's scope. foo will only be aware of its internal scope since it may be being called by countless other modules and applications.
To get the current file module, containing folder, here is what worked for me:
import os
parts = os.path.splitext(__name__)
module_name = parts[len(parts) - 2]
To obtain a reference to the "__main__" module when in another:
import sys
sys.modules['__main__']
To then obtain the module's file path, which includes its name:
sys.modules['__main__'].__file__
If within the "__main__" module, simply use: __file__
To obtain just the file name from the file path:
import os
os.path.basename(file_path)
To separate the file name from its extension:
file_name.split(".")[0]
To obtain the name of a class instance:
instance.__class__.__name__
To obtain the name of a class:
class.__name__