Rishabh Agrahari
Rishabh Agrahari

Reputation: 3717

Difference between os.path.dirname(os.path.abspath(__file__)) and os.path.dirname(__file__)

settings.py file of a Django project contains these two lines:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

I want to know the difference as I think both are pointing to the same directory. Also it would be great help if you could provide some links os.path functions.

Upvotes: 35

Views: 90280

Answers (2)

cottontail
cottontail

Reputation: 23151

Suppose you started your project using the django-admin startproject my_new_app command, then it creates a hierarchy as follows.

my_new_app
|
└───my_new_app
│   │   
│   │   settings.py
│   │   ...
|   manage.py

Then, os.path.abspath(__file__) returns the absolute path to the settings.py file, os.path.dirname(os.path.abspath(__file__)) returns the path to the inner my_new_app folder and os.path.dirname(os.path.dirname(os.path.abspath(__file__))) returns the path to the outer my_new_app folder.

In more recent versions of Django (e.g. version 4.2.5), instead of os, pathlib module is used, so an equivalent construct is:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
PROJECT_ROOT = Path(__file__).resolve().parent

There's a special case where if settings.py is already in the root directory on your environment (e.g. the C drive on a local machine) so that its path looks like C:\settings.py, then BASE_DIR == PROJECT_ROOT may be True. This is probably not how it should be, so if BASE_DIR and PROJECT_ROOT are the same, then you probably need to re-structure your project.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1122142

BASE_DIR is pointing to the parent directory of PROJECT_ROOT. You can re-write the two definitions as:

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
BASE_DIR = os.path.dirname(PROJECT_ROOT)

because the os.path.dirname() function simply removes the last segment of a path.

In the above, the __file__ name points to the filename of the current module, see the Python datamodel:

__file__ is the pathname of the file from which the module was loaded, if it was loaded from a file.

However, it can be a relative path, so the os.path.abspath() function is used to turn that into an absolute path before removing just the filename and storing the full path to the directory the module lives in in PROJECT_ROOT.

Upvotes: 47

Related Questions