Reputation: 19329
Example1 where path2 starts with '/' results to /dir2/dir3/
(missing path1)
path1='/Volumes/disk1/'
path2='/dir2/dir3/'
print os.path.join(path1,path2)
Example2 where path2 does NOT start with '/' results to proper /Volumes/disk1/dir2/dir3/
:
path1='/Volumes/disk1/'
path2='dir2/dir3/'
print os.path.join(path1,path2)
Question: I thought the purpose of os.path.join() is allow us to avoid extra work of tedious work of verifying if it's mac, windows or linux file path: one command does it all. But now if I would have to watch if path2
starts or does not start with '/' (or '\') it ruins every hope I had and brings ton of extra code... What is the solution? I don't want to do this ugliness:
if path2 and path2.replace('\\','/')[1:] and path2.replace('\\','/').startswith('/'):
path2=path2[1:]
Upvotes: 2
Views: 712
Reputation: 47078
In order to work without the hassle of checking separators you have to start without them or remove them completely before passing to os.path.join()
. In the code below, I show 3 ways you can do this (Live Ideone Example to play with).
import os
print os.path.join('Volumes', 'disk1', 'dir2', 'dir3')
path1 = '/Volumes/disk1/'
path2 = '/dir2/dir3/'
import os
# this will convert to the same as above:
# i.e., os.path.join('Volumes', 'disk1', 'dir2', 'dir3')
print os.path.join(*(path1.split(os.sep) + path2.split(os.sep)))
Using the above code, you can write a custom join()
that works for either single- or multi- path strings:
def join(*paths):
import os
return os.path.join(*[part for path in paths for part in path.split(os.sep)])
path1 = '/Volumes/disk1/'
path2 = '/dir2/dir3/'
print join(path1, path2)
Output:
'Volumes/disk1/dir2/dir3'
Upvotes: 1
Reputation: 9085
Direct form the documentation,
Join one or more path components intelligently. If any component is an absolute path, all previous components (on Windows, including the previous drive letter, if there was one) are thrown away, and joining continues.
You're seeing the behavior you are because you are passing it an absolute path (a path that starts with a '/'
). Your program needs to be able to handle the difference between the two, and if it's the thing generating the paths, make sure it's probably creating an absolute path when you want that, and a relative one when you want that.
Explanation of why this is useful
Consider the following. I have a command line interface that asks the user to specify a path for file output. In my documentation, I say the following:
path: Path to an output file. If relative, will be placed inside ~/Documents.
Now in my code, all I need to do is:
out_path = os.path.join('~','Documents', path)
and now out_path
will always contain the correct path. If the user specifies volume_1/output.txt
, the file will wind up in ~/Documents/volume_1/output.text
. If they specify /mnt/volume_1/output.text
it will wind up in /mnt/volume_1/output.text
, because the absolute path overrides the relative portion we provide as a default.
Upvotes: 1