为什么在Python中我被迫使用os.path.expanduser?

26

我确定这是有意的,那么能否有人解释一下这种行为的原理:

Python 2.7.2 (default, Oct 13 2011, 15:27:47) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from os.path import isdir,expanduser
>>> isdir("~amosa/pdb")
False
>>> isdir(expanduser("~amosa/pdb"))
True
>>>
>>> from os import chdir
>>> chdir("~amosa/pdb")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: '~amosa/pdb'
>>> chdir(expanduser("~amosa/pdb"))
>>>

这真的很恼人,因为毕竟带有用户名的路径可以明确解析... 我想编写能够处理用户可能提供给我的任何类型输入的代码,但这种行为要求我对我的代码所涉及的每个路径调用expanduser。这也意味着在任何我为用户查看的地方打印该路径,它将比他们给我的略微难以阅读。

这似乎与“鸭子类型”的概念不一致,其中我通常会推广到我期望Python不会向我抱怨,除非实际上存在问题...


8
作为一名Python开发者,我很欣赏Python不会自动地对字符串进行扩展,除非我明确请求这种行为。如果你正确实现代码,你可以将对expanduser的调用集中起来,使其不再烦人。我不知道。 - larsks
4
chdir 假设它是一个字面名称,这绝对不是鸭子类型的意思。 - Chris Eberle
创建一个函数来处理所有的行为。Python 为您提供了核心功能。 - Blender
2个回答

27
因为底层系统调用无法识别用户路径,文件访问API只是对它们的一个非常薄的包装。
此外,对于非Unix用户来说,如果(例如)fopen("~foo")返回“foo: no such user”错误(因为“~foo”是合法的文件名,例如在Windows上)将会相当令人惊讶...或者,类似地,如果fopen("~administrator")返回类似“Is a directory: C:\Documents and Settings\Administrator\"的错误信息。
最后,正如评论者所指出的那样:你混淆了“鸭子类型”和“有用的快捷方式”,这两个完全不同:
- 鸭子类型允许我用任何像鸭子一样嘎嘎叫的东西代替鸭子。
- 有用的快捷方式允许我用任何可能被制造成像鸭子一样嘎嘎叫的东西代替鸭子。(Python不会像其他一些语言那样“试图使其嘎嘎叫”)。

2
在Linux和大多数其他POSIX环境中,“~foo”也是一个有效的名称。 - SingleNegationElimination
我认为在我的脑海中,鸭子类型是在抱怨之前先“尝试让它嘎嘎叫”。在这种情况下,Python 并没有尽最大努力。我非常喜欢 Python,因为它很容易编写代码并且能够正常工作。但是当涉及到让 Python 进行 shell 脚本编写时,我发现自己需要编写很多自己的实用程序代码。 - amos
2
啊,是的 - 这就是区别所在。Python不像其他一些语言那样“试图让它嘎嘎叫”(例如,Python对于1 +“2”object().foo和引用未定义变量会抛出错误)。 - David Wolever

11

在普通的Unix工具中,~amosa语法由shell处理,而shell是调用工具的程序。工具本身通常不知道特殊的~语法。

因此,如果您的Python程序是由Unix上的shell调用的,它将可以正常工作:

$ python -c 'import sys; print sys.argv[1]' ~drj
/home/drj

注意上面的Python程序如何打印出扩展后的路径,尽管它明显没有代码来执行这个扩展。这是因为shell已经对其进行了扩展。


2
这是一个有用的提示,因为在从命令行接受输入的程序中,对于初学者来说,似乎 Python 确实进行了扩展,尽管实际上是 shell 在执行扩展。这可能会导致困惑,当需要编程或从用户输入添加文件名时,这种扩展不会发生。 - zstewart

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