为什么Python路径库中的Path('').exists()会返回True?

16
我原本以为 Path('') 是一个不存在的路径,因为它不对应于文件或目录名称。为什么它被认为是存在的呢?
from pathlib import Path

print(Path('').exists())

我认为将Path('')定义为与Path('.')相同,会获得优势。在什么情况下会有优势呢?

6
因为它解析为当前目录,而当前目录是存在的。 - Peter Wood
请看 Path('') == Path() == Path('.') - Patrick Haugh
尝试运行 print(Path('').resolve())。在我的电脑上,它会输出 C:\Users\PeterWood\AppData\Local\Programs\Python\Python36-32 - Peter Wood
3个回答

18

正如其他人所说,它解析为当前路径,因此存在,但这是原因:

pathlib.Path 实际上是 pathlib.PurePath 的子类,当 pathsegments(参数)为空时(相当于''),它假定为当前目录。

您可以通过以下方法经验性地证明:

from pathlib import PurePath
print(PurePath())
>>>> .

我认为将Path('')定义为与Path('.')相同会带来优势。

是的。虽然我不是该库的创建者,但我认为这是出于语法和逻辑原因。实际上,人们经常想要引用当前目录来动态计算某些内容。因此,出于同样的原因,.指向当前目录,库的创建者可能希望让你这样写:

>>>> p = Path() # or possibly Path('.')
>>> [x for x in p.iterdir() if x.is_dir()]

这将列出子目录。

基本上,将其视为默认值。逻辑上讲,Path() 返回的默认路径应该是当前目录。因此,空字符串值应具有相同的行为。


@mattm 考虑接受这个答案。我认为它是有效的。 - Dinko Pehar

5
如果你尝试使用stat,你会得到以下结果:
$ touch ""
touch: cannot touch '': No such file or directory

但是如果你深入了解,情况就会不同:

$ strace -e file touch ""
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=122530, ...}, AT_EMPTY_PATH) = 0
openat(AT_FDCWD, "", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = -1 ENOENT (No such file or directory)

所以你可以使用""表示当前工作目录,但是你无法将其作为文件打开,因为该文件不存在。事实上:
$ strace -e file ipython3 
In [1]: import pathlib

In [2]: p = pathlib.Path()

In [3]: p.exists()
newfstatat(AT_FDCWD, ".", {st_mode=S_IFDIR|0755, st_size=20480, ...}, 0) = 0
Out[3]: True

因此,这不仅仅是Python的pathlib模块的任何假设,而是延伸到C库和内核。


2
稍微偏题:我想要一个布尔值为False的路径(Path)。看起来好像不可能。我在argparse中使用type=Path实现这个操作。我猜想OP(OP是什么?)也希望得到类似的东西。

最终我采用了以下两种方式之一,虽然都没有像“如果the_possibly_false_Path为真,则...”那样“优美”:

  1. 将默认值(我希望测试为False)设置为类似于“%%”这样的内容,这会导致argparse创建一个名为“%%”的路径,从而可以进行测试
  2. 将结果留作默认类型,将默认值设置为测试为假的某些内容,然后在值不为false时调用路径构造函数。

一样。但也许引发异常是更好的方式。个人而言,我不喜欢通过引发异常来执行基本上是if-else操作,但是... - Jacob Lee

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