Relative versus absolute paths on Windows

Jason R. Coombs jaraco at jaraco.com
Thu Nov 19 11:37:35 EST 2009


The current implementation of Python (2.6.4, 3.1.1) treats \bar as a
relative path but reports it as an absolute path.

>>> ntpath.isabs('\\bar')
True
>>> ntpath.abspath('\\bar')
'C:\\bar'
>>> os.chdir('d:\\')
>>> ntpath.abspath('\\bar')
'd:\\bar'
>>> os.chdir('\\\\server\\share')
>>> ntpath.abspath('\\bar')
'\\\\server\\share\\bar'

In other words, paths without a drive letter are reported as absolute,
but treated as relative, except in a few special cases.

>>> ntpath.join('d:\\foo', '\\bar')
'\\bar'

In this case, \bar is treated as absolute, and not relative to d:\foo.

This inconsistency means that to effectively resolve one path relative
to another, one has to resort to explicit drive letter manipulation.
See http://stackoverflow.com/questions/1654659/find-a-path-in-windows-relative-to-another
for a case in point.

My understanding is that in Windows, a path is only absolute if it
contains a drive letter or it begins with a double-backslash.

Curiously, the .Net Framework seems to be subject to the same
limitation

# using IronPython 2.6RC2
>>> System.IO.Path.IsPathRooted('\\bar')
True
>>> System.IO.Path.Combine('d:\\foo', '\\bar') # expect d:\bar
'\\bar'

The documentation for Combine raises this issue in the Community
Content (http://msdn.microsoft.com/en-us/library/fyy7a5kt.aspx).

Furthermore, the Windows API utility is also consistent with this odd
behavior (http://msdn.microsoft.com/en-us/library/bb773660%28VS.
85%29.aspx).

The discussion here (http://groups.google.com/group/comp.os.ms-
windows.programmer.win32/browse_thread/thread/b2ff7a9d1d7c9b5e)
describes absolute paths consistent with my understanding:

  Absolute paths have these characteristics.
  Length is at least 2 characters, AND
  ( Second character is ":", OR First two characters is "\\" )

And according to WikiPedia (http://en.wikipedia.org/wiki/Path_
%28computing%29), "[an] absolute path is a path that points to the
same location on one file system regardless of the working directory."
By this definition, \bar is a relative path on Windows.

Ultimately, I don't care what the definition is. It seems to me,
however, that Python should have a function that can resolve one path
name relative to another, but due to these limitations, it does not. I
should point out that os.path.relpath is not the solution either as
the first parameter is always treated as relative to the current
directory (more info at http://bugs.python.org/issue7195).

I've built workarounds in https://svn.jaraco.com/jaraco/python/jaraco.windows/jaraco/windows/filesystem.py
as join() and resolve_path(). I'm happy to continue using these
workarounds, but I wanted to bring this issue to the attention of the
community for any comments or suggestions or answers to the following
questions.

What is the benefit of treating \path as absolute?
Should Python have built-in support for resolving one path relative to
another (such as is jaraco.windows.filesystem.resolve_path does)?
Given the long established behavior of Python and other platforms for
handling absolute paths in Windows, is there a way forward that
handles these cases more elegantly, or is the best approach to just
mumble something nasty under our breath and work around these issues
on a case-by-case basis?



More information about the Python-list mailing list