constructing absolute path with os.path.join()
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:\etc\init.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)
Using os.sep
as root worked for me:
path.join(os.sep, 'python', 'bin')
Linux: /python/bin
Windows: \python\bin
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:\python\bin
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?
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')
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