How to refer to relative paths of resources when working with a code repository
I often use something similar to this:
import os
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir'))
# if you have more paths to set, you might want to shorten this as
here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x))
DATA_DIR = here('datadir')
pathjoin = os.path.join
# ...
# later in script
for fn in os.listdir(DATA_DIR):
f = open(pathjoin(DATA_DIR, fn))
# ...
The variable
__file__
holds the file name of the script you write that code in, so you can make paths relative to script, but still written with absolute paths. It works quite well for several reasons:
- path is absolute, but still relative
- the project can still be deployed in a relative container
But you need to watch for platform compatibility - Windows' os.pathsep is different than UNIX.
In Python, paths are relative to the current working directory, which in most cases is the directory from which you run your program. The current working directory is very likely not as same as the directory of your module file, so using a path relative to your current module file is always a bad choice.
Using absolute path should be the best solution:
import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
If you are using setup tools or distribute (a setup.py install) then the "right" way to access these packaged resources seem to be using package_resources.
In your case the example would be
import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")
Which of course reads the resource and the read binary data would be the value of my_data
If you just need the filename you could also use
resource_filename(package_or_requirement, resource_name)
Example:
resource_filename("MyPackage","foo.dat")
The advantage is that its guaranteed to work even if it is an archive distribution like an egg.
See http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api
Try to use a filename relative to the current files path. Example for './my_file':
fn = os.path.join(os.path.dirname(__file__), 'my_file')
In Python 3.4+ you can also use pathlib:
fn = pathlib.Path(__file__).parent / 'my_file'