constructing absolute path with os.path.join()

Question:

I’d like to construct an absolute path in python, while at the same time staying fairly oblivious of things like path-separator.

edit0: for instance there is a directory on the root of my filesystem /etc/init.d (or C:etcinit.d on w32), and I want to construct this only from the elements etc and init.d (on w32, I probably also need a disk-ID, like C:)

In order to not having to worry about path-separators, os.join.path() is obviously the tool of choice. But it seems that this will only ever create relative paths:

 print("MYPATH: %s" % (os.path.join('etc', 'init.d'),)
 MYPATH: etc/init.d

Adding a dummy first-element (e.g. '') doesn’t help anything:

 print("MYPATH: %s" % (os.path.join('', 'etc', 'init.d'),)
 MYPATH: etc/init.d

Making the first element absolute obviously helps, but this kind of defeats the idea of using os.path.join()

 print("MYPATH: %s" % (os.path.join('/etc', 'init.d'),)
 MYPATH: /etc/init.d

edit1: using os.path.abspath() will only try to convert a relative path into an absolute path.
e.g. consider running the following in the working directory /home/foo:

 print("MYPATH: %s" % (os.path.abspath(os.path.join('etc', 'init.d')),)
 MYPATH: /home/foo/etc/init.d

So, what is the standard cross-platform way to "root" a path?

 root = ??? # <--
 print("MYPATH: %s" % (os.path.join(root, 'etc', 'init.d'),)
 MYPATH: /etc/init.d

edit2: the question really boils down to: since the leading slash in /etc/init.d makes this path an absolute path, is there a way to construct this leading slash programmatically?
(I do not want to make assumptions that a leading slash indicates an absolute path)

Asked By: umläute

||

Answers:

So you can do a check for running os
by sys.platfrom

on windows

>>> sys.platform
'win32'

on linux

>>> sys.platform
'linux2'

then

if sys.platform == 'win32':
    ROOT = os.path.splitdrive(os.path.abspath('.'))[0]
elif sys.platform == 'linux2':
    ROOT = os.sep

Please note that ‘linux2’ may not cover all linux distros

Answered By: Ansuman Bebarta

you could try with os.path.splitdrive to get the name of your drive/filesystem, then join this with your foo string.

http://docs.python.org/2/library/os.path.html#os.path.splitdrive

something like (untested!)

(drive, tail) = os.path.splitdrive(os.getcwd())
os.path.join(drive, 'foo')

should do the trick.

Answered By: Christoph

so the solution i came up with, is to construct the root of the filesystem by following a given file to it’s root:

def getRoot(file=None):
  if file is None:
      file='.'
  me=os.path.abspath(file)
  drive,path=os.path.splitdrive(me)
  while 1:
    path,folder=os.path.split(path)
    if not folder:
       break
  return drive+path

 os.path.join(getRoot(), 'etc', 'init.d')
Answered By: umläute

I think you can use os.path.normpath. Here’s what I get on Windows:

>>> os.path.normpath("/etc/init.d")
'\etc\init.d'

I’m not sure exactly what the right thing to do with the drive prefix is, but I think leaving it off means something like “keep using the drive I’m on now,” which is probably what you want. Maybe someone more familiar with Windows can clarify?

Answered By: Jack O'Connor

Using os.sep as root worked for me:

path.join(os.sep, 'python', 'bin')

Linux: /python/bin

Windows: pythonbin

Adding path.abspath() to the mix will give you drive letters on Windows as well and is still compatible with Linux:

path.abspath(path.join(os.sep, 'python', 'bin'))

Linux: /python/bin

Windows: C:pythonbin

Answered By: girardc79
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.