Django and Relativity Updated

Currently it's the season of EuroDjangoCon and I'm reading various presentations. One interesting thing I'm seeing is that many people are using relative paths in their settings.py file but in different ways. (For reference, see Django and Relativity). So far I've seen:

  1. os.path.dirname(__file__)
  2. os.path.abspath(os.path.dirname(__file__))
  3. os.path.realpath(os.path.dirname(__file__))

I've reviewed the 3 ways provided here and looked at the Python source for verification. Let's talk about each one briefly...

1) dirname

PROJECT_ROOT = os.path.dirname(__file__)

While the above might work in most cases, it's the worst choice of the three in that it provides a relative path, it's the least portable across different operating systems and the least canonical in terms of the returned URL. More about each of these points in items 2 and 3 below.

2) dirname plus abspath

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

What this adds to the previous example is wrapping the given directory name with os.path.abspath. According to the Python docs, what this does is "Return a normalized absolutized version of the pathname". So there are two extra bits this is doing:

  1. "Absolutizes" the path. For example, something like path/to/project might turn into /var/www/path/to/project.
  2. Normalizes the path. For example, on Unix and Mac OS X systems the path /var/www/project will work fine, but on Windows systems that is not a good path. Normalizing the path will convert forward slashes to backward slashes. Normalization also collapses redundant separators, for example the path A/foo/../B will be normalized to A/B.

This is actually what I've been using and is a good candidate. But there's one extra thing that is better, in my opinion.

3) dirname plus realpath

PROJECT_ROOT = os.path.realpath(os.path.dirname(__file__))

According to the Python documentation, realpath will return the canonical path and will eliminate any symbolic links, providing the true path to the directory. It wasn't clear from the documentation if this also does what abspath and normpath do but after reviewing the Python source for each path implementation, it does call abspath, which in turn calls normpath. Note, however, that on Windows this has no effect since Windows, "realpath is a no-op on systems without islink support".

This might be a debatable choice but it's the one I'm going to use from now on as the most true path and the most portable. Others may prefer abspath instead of realpath.

Hopefully this quick blog post clarified some differences between these to make the best choice for your situation. For further reading, visit the Python docs for the os.path module.

About this entry

Date Posted:
May 5th 2009 at 11:05:07 AM

Tagged:
django, relative

Previous Entry:
Testing Emails with Django

Next Entry:
DjangoCon 2009 Day 1