what does the __file__ variable mean/do?
PythonPython Problem Overview
import os
A = os.path.join(os.path.dirname(__file__), '..')
B = os.path.dirname(os.path.realpath(__file__))
C = os.path.abspath(os.path.dirname(__file__))
I usually just hard-wire these with the actual path. But there is a reason for these statements that determine path at runtime, and I would really like to understand the os.path
module so that I can start using it.
Python Solutions
Solution 1 - Python
When a module is loaded from a file in Python, __file__
is set to its path. You can then use that with other functions to find the directory that the file is located in.
Taking your examples one at a time:
A = os.path.join(os.path.dirname(__file__), '..')
# A is the parent directory of the directory where program resides.
B = os.path.dirname(os.path.realpath(__file__))
# B is the canonicalised (?) directory where the program resides.
C = os.path.abspath(os.path.dirname(__file__))
# C is the absolute path of the directory where the program resides.
You can see the various values returned from these here:
import os
print(__file__)
print(os.path.join(os.path.dirname(__file__), '..'))
print(os.path.dirname(os.path.realpath(__file__)))
print(os.path.abspath(os.path.dirname(__file__)))
and make sure you run it from different locations (such as ./text.py
, ~/python/text.py
and so forth) to see what difference that makes.
Solution 2 - Python
I just want to address some confusion first. __file__
is not a wildcard it is an attribute. Double underscore attributes and methods are considered to be "special" by convention and serve a special purpose.
http://docs.python.org/reference/datamodel.html shows many of the special methods and attributes, if not all of them.
In this case __file__
is an attribute of a module (a module object). In Python a .py
file is a module. So import amodule
will have an attribute of __file__
which means different things under difference circumstances.
Taken from the docs:
> __file__
is the pathname of the file from which the module was loaded, if it was loaded from a file. The __file__
attribute is not present
> for C modules that are statically linked into the interpreter; for
> extension modules loaded dynamically from a shared library, it is the
> pathname of the shared library file.
In your case the module is accessing it's own __file__
attribute in the global namespace.
To see this in action try:
# file: test.py
print globals()
print __file__
And run:
python test.py
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__file__':
'test_print__file__.py', '__doc__': None, '__package__': None}
test_print__file__.py
Solution 3 - Python
Per the documentation:
> __file__
is the pathname of the file from which the module was
> loaded, if it was loaded from a file. The __file__
attribute is not
> present for C modules that are statically linked into the interpreter;
> for extension modules loaded dynamically from a shared library, it is
> the pathname of the shared library file.
and also:
> __file__
is to be the “path” to the file unless the module is built-in (and thus listed in sys.builtin_module_names
) in which case the attribute is not set.
Solution 4 - Python
Just going to add a quick note here (mostly answering the question's title rather than its description) about a change which can confuse some people. As of Python 3.4 there has been a slight change in how the __file__
behaves:
- It's set to the relative path of the module in which it's used, if that module is executed directly.
- It's set to the absolute path of the file otherwise.
> Module __file__
attributes (and related values) should now always contain absolute paths by default, with the sole exception of __main__.__file__
when a script has been executed directly using a relative path. (Contributed by Brett Cannon in issue 18416.)
Example:
Calling module x directly and module y indirectly:
# x.py:
from pathlib import Path
import y
print(__file__)
print(Path(__file__))
print(Path(__file__).resolve())
# y.py:
from pathlib import Path
print(__file__)
print(Path(__file__))
Running python3 x.py
will output:
/home/aderchox/mytest/y.py
/home/aderchox/mytest/y.py
x.py
x.py
/home/aderchox/mytest/x.py
Solution 5 - Python
Using __file__
combined with various os.path
modules lets all paths be relative the current module's directory location. This allows your modules/projects to be portable to other machines.
In your project you do:
A = '/Users/myname/Projects/mydevproject/somefile.txt'
and then try to deploy it to your server with a deployments directory like /home/web/mydevproject/
then your code won't be able to find the paths correctly.