How to read a file in a module by its relative path to the module?

Viewed 52

The directory structure:

├--- mod
|    ├--- __init__.py
|    └--- abc.data
└--- test.py

__init__.py:

with open("abc.data", 'r') as f:
    pass # read and process the data

test.py:

import mod

The program above is expected to read the data in the file abc.data, but it gives an error instead:

FileNotFoundError: [Errno 2] No such file or directory: 'abc.data'

And this is because the current directory of Python interpreter is the parent directory of test.py.

So how to read abc.data in the module mod regardless of the location of test.py?


Actually the following code works:

__init__.py:

import os
filepath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "abc.data")
with open(filepath, 'r') as f:
    pass # read and process the data

But this solution is a bit dirty especially when there are many files to be read in __init__.py. Is there a more elegant solution?

1 Answers

I believe that's as good as it gets. Even larger libraries use the same method:

# Extracted From selenium/webdriver/firefox/firefox_profile.py

# ...
if not FirefoxProfile.DEFAULT_PREFERENCES:
            with open(os.path.join(os.path.dirname(__file__),
                                   WEBDRIVER_PREFERENCES)) as default_prefs:
                FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)
# ...

Another example:

# Extracted from pipenv/vendor/yaspin/spinners.py

# ... 
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
SPINNERS_PATH = os.path.join(THIS_DIR, "data/spinners.json")
# ...

If it was an importable object (e.g. .py files) then you can use . conventions to indicate the relative path.

Related