Problem
I’m trying to figure out if a module has changed. Inotify is very simple to use; all you need to know is which directory you wish to receive notifications from.
In Python, how do I get the path of a module?
Asked by Cheery
Solution #1
import a_module
print(a_module.__file__)
On Mac OS X, this will really provide you the path to the.pyc file that was loaded. So, I suppose you could:
import os
path = os.path.abspath(a_module.__file__)
Alternatively, you might try:
path = os.path.dirname(a_module.__file__)
To retrieve the directory for the module.
Answered by orestis
Solution #2
Python has an inspect module.
Example:
>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'
Answered by Tomas Tomecek
Solution #3
The best method to do this, as previous responses have shown, is to use __file__ (demonstrated again below). However, there is one essential caveat: if you run the module on its own (i.e. as __main__), __file__ does not exist.
Consider the following two files (both of which are located in your PYTHONPATH):
#/path1/foo.py
import bar
print(bar.__file__)
and
#/path2/bar.py
import os
print(os.getcwd())
print(__file__)
The following is the outcome of running foo.py:
/path1 # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs
If you try to run bar.py on its own, though, you’ll get:
/path2 # "print(os.getcwd())" still works fine
Traceback (most recent call last): # but __file__ doesn't exist if bar.py is running as main
File "/path2/bar.py", line 3, in <module>
print(__file__)
NameError: name '__file__' is not defined
I hope this information is useful. While testing the other alternatives, this caveat cost me a lot of time and confusion.
Answered by mcstrother
Solution #4
I’ll also try to answer a couple versions of this question:
(Some of these questions were originally posted on SO, but they were marked as duplicates and redirected here.)
If you’ve imported a module, you’ll need to do the following:
import something
something.__file__
will return the module’s absolute path. However, using the foo.py script as an example:
#foo.py
print '__file__', __file__
Using the ‘python foo.py’ command will just return ‘foo.py’. If you throw in a shebang:
#!/usr/bin/python
#foo.py
print '__file__', __file__
It will return ‘./foo.py’ if you call it with./foo.py. Calling it from a different directory (e.g., foo.py in directory bar), then calling one of the two methods.
python bar/foo.py
Alternatively, you can add a shebang and run the file directly:
bar/foo.py
‘bar/foo.py’ will be returned (the relative path).
From there, using os.path.dirname( file ) to find the directory can be hard. If you call it from the same directory as the file, it returns an empty string, at least on my machine. ex.
# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)
will output:
__file__ is: foo.py
os.path.dirname(__file__) is:
In other words, it returns an empty string, which makes it untrustworthy for usage with the current file (as opposed to the file of an imported module). You can get around this by wrapping it in an abspath call:
# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))
It produces something along the lines of:
os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar
It’s worth noting that abspath() doesn’t work with symlinks. If you wish to achieve this, instead use realpath(). Create a symlink named file import testing link that points to file import testing.py and has the following content:
import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)
executing will output absolute paths such as:
abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py
file_import_testing_link -> file_import_testing.py
The inspect module is mentioned by @SummerBreeze.
For imported modules, this appears to function well and is pretty concise:
import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)
Returns the absolute path obediently. To get the path of the currently running script, use the following formula:
inspect.getfile(inspect.currentframe())
(thanks @jbochi)
inspect.getabsfile(inspect.currentframe())
gives the absolute path of currently executing script (thanks @Sadman_Sakib).
Answered by jpgeek
Solution #5
I’m not sure why no one has mentioned it, but the simplest approach for me is to use imp.find module(“modulename”) (documentation here):
import imp
imp.find_module("os")
It returns a tuple in which the path is in second place:
(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))
The advantage of this technique over the “inspect” method is that it doesn’t require you to import the module and you may use a string as input. For example, while inspecting modules called from another script.
EDIT:
The importlib module in Python 3 should accomplish the following:
Doc of importlib.util.find_spec:
Answered by PlasmaBinturong
Post is based on https://stackoverflow.com/questions/247770/how-to-retrieve-a-modules-path