HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Accessing the contents of a project's root directory in Python

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
directorythecontentsprojectrootpythonaccessing

Problem

This morning I was trying to find a good way of using os.path to load the content of a text file into memory, which exists in the root directory of my current project.

This approach strikes me as a bit hackneyed, but after some thought it was exactly what I was about to do, except with os.path.normpath(os.path.join(__file__, '..', '..'))

These relative operations on the path to navigate to a static root directory are brittle.

Now, if my project layout changes, these associations to the (former) root directory change with it. I wish I could assign the path to find a target, or a destination, instead of following a sequence of navigation operations.

I was thinking of making a special __root__.py file. Does this look familiar to anyone, or know of a better implementation?

my_project
|
| __init__.py
| README.md
| license.txt
| __root__.py
| special_resource.txt
| ./module
  |-- load.py


Here is how it is implemented:

"""__root__.py"""
import os
def path():
    return os.path.dirname(__file__)


And here is how it could be used:

"""load.py"""
import __root__
def resource():
    return open(os.path.join(__root__.path(), 'special_resource.txt'))

Solution

I never heard of __root__.py and don't think that is a good idea.

Instead create a files.py in a utils module:

MAIN_DIRECTORY = dirname(dirname(__file__))
def get_full_path(*path):
    return join(MAIN_DIRECTORY, *path)


You can then import this function from your main.py:

from utils.files import get_full_path

path_to_map = get_full_path('res', 'map.png')


So my project directory tree looks like this:

project_main_folder/
    utils/
        __init__.py (empty)
        files.py
    main.py


When you import a module the Python interpreter searches if there's a built-in module with that name (that's why your module name should be different or you should use relative imports). If it hasn't found a module with that name it will (among others in sys.path) search in the directory containing your script. You can find further information in the documentation.

Code Snippets

MAIN_DIRECTORY = dirname(dirname(__file__))
def get_full_path(*path):
    return join(MAIN_DIRECTORY, *path)
from utils.files import get_full_path

path_to_map = get_full_path('res', 'map.png')
project_main_folder/
    utils/
        __init__.py (empty)
        files.py
    main.py

Context

StackExchange Code Review Q#20428, answer score: 5

Revisions (0)

No revisions yet.