os.path.join()的行为是否正常?
示例1中,path2以'/'开头,结果是 /dir2/dir3/
(缺少了path1)
path1='/Volumes/disk1/'
path2='/dir2/dir3/'
print os.path.join(path1,path2)
示例2中,path2没有以'/'开头,结果是正确的 /Volumes/disk1/dir2/dir3/
:
path1='/Volumes/disk1/'
path2='dir2/dir3/'
print os.path.join(path1,path2)
问题:我原以为os.path.join()的目的就是让我们避免繁琐的工作,比如检查文件路径是mac、windows还是linux:一个命令就能搞定。但现在如果我还得去注意path2
是以'/'(或者'\')开头还是不开头,这让我之前的希望都破灭了,还要增加很多额外的代码……那有什么解决办法吗?我不想做这种麻烦的事情:
if path2 and path2.replace('\\','/')[1:] and path2.replace('\\','/').startswith('/'):
path2=path2[1:]
2 个回答
直接来自文档的内容,
智能地连接一个或多个路径组件。如果任何组件是绝对路径,那么之前的所有组件(在Windows上,包括之前的驱动器字母,如果有的话)都会被丢弃,然后继续连接。
你看到这样的行为是因为你传入了一个绝对路径(以'/'
开头的路径)。你的程序需要能够处理这两者之间的区别,如果是程序自己生成路径,确保在需要绝对路径时生成绝对路径,在需要相对路径时生成相对路径。
为什么这很有用的解释
考虑以下情况。我有一个命令行界面,要求用户指定一个文件输出的路径。在我的文档中,我这样说明:
path: Path to an output file. If relative, will be placed inside ~/Documents.
现在在我的代码中,我只需要这样做:
out_path = os.path.join('~','Documents', path)
现在out_path
将始终包含正确的路径。如果用户指定volume_1/output.txt
,文件将会出现在~/Documents/volume_1/output.txt
中。如果他们指定/mnt/volume_1/output.txt
,文件将会出现在/mnt/volume_1/output.txt
中,因为绝对路径会覆盖我们提供的默认相对路径。
为了避免检查路径分隔符的麻烦,你需要在开始时就不使用它们,或者在传递给 os.path.join()
之前完全去掉它们。下面的代码展示了三种可以做到这一点的方法(你可以通过这个在线示例来试试)。
单独的目录
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)))
自定义合并函数
使用上面的代码,你可以写一个自定义的 join()
函数,适用于单个或多个路径字符串:
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)
输出:
'Volumes/disk1/dir2/dir3'