为什么os.path.join会丢弃参数?

14

我正在学习Python,发现我的一个脚本出现了一些奇怪的问题。经过一些测试,我发现问题源自这种行为:

>>> import os
>>> os.path.join('a','b')
'a/b'
>>> os.path.join('a','/b')
'/b'

查看文档,事实上这就是该函数的设计:

os.path.join(path1[, path2[, ...]])

智能地连接一个或多个路径组件。如果任何组件是绝对路径,则丢弃所有先前的组件(在 Windows 上,包括以前的驱动器号(如果有)),然后继续连接...

我的问题不是 为什么我的脚本失败了,而是为什么函数被设计成这样。 我的意思是,在Unix上至少,`a//b` 是一种完全可以接受的方式来指定路径,即使不够优雅。 为什么要这样设计函数?是否有办法判断是否舍弃了一个或多个路径元素,而无需使用os.path.isabs()测试每个路径字符串?


出于好奇,我也检查了路径组件以os.sep字符结尾的情况:

>>> os.path.join('a/','b')
'a/b'

那个按预期工作。


一种简单但不太优雅的方法是使用filename.lstrip('/')来检查这个。 - voithos
4
把它改为 filename.lstrip(os.sep),这样就可以适用于大多数主要平台了。 - user395760
2
@Martijn 为了尽可能地通用,它应该是 os.sep + (os.altsep or "") - Lauritz V. Thaulow
在我看来,这是创建路径组合函数的完全合理的方式。 - Lightness Races in Orbit
@jon-ericson 是的,非常奇怪。可能是为了防止将其视为网络路径引用。 - Delimitry
显示剩余3条评论
2个回答

15

os.path.join('a', '/b') 返回 /b 有用的情况之一是当您要求用户提供文件名时。

用户可以输入相对于当前目录的路径或完整路径,您的程序可以像这样处理两种情况:

os.path.join(os.getcwd(), filename)

In [54]: os.getcwd()
Out[54]: '/tmp'

In [55]: os.path.join(os.getcwd(), 'foo')
Out[55]: '/tmp/foo'

In [56]: os.path.join(os.getcwd(), '/foo/bar')
Out[56]: '/foo/bar'

1
...或者任何其他目录,只要应用程序有一个合理的默认目录。 - user395760
4
Guido从最初的修订版就考虑了这一点(函数最初名为“cat”,后来更名为“join”)。链接 - Martijn Pieters
1
@Martijn Pieters:非常有趣。我很好奇Guido是否曾经解释过设计背后的目的。同时感谢unutbu指出了一个有意义的用例。 - Jon Ericson

1

如果你正在编写一个类似于cd的实用程序来检查新目录,你可以使用以下命令:

os.path.join(currdir, newdir)

如果用户输入/b,您应该期望它抛出第一个参数。这适用于许多使用当前目录的事情。

但是...如果我想编写一个类似于“复制”的实用程序,将文件从绝对路径复制到另一个基本目录,并保留父目录,我希望“/path/to/file”与“/path/to/new/dest/dir”连接而不会丢失任何内容 ;) - Henning

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接