PEP 235 – 不区分大小写的平台上的导入
- 作者:
- Tim Peters <tim.peters at gmail.com>
- 状态:
- 最终
- 类型:
- 标准跟踪
- 创建:
- 2001-02-21
- Python 版本:
- 2.1
- 发布历史:
- 2001-02-16
注意
这本质上是一个追溯性的 PEP:这个问题在 2.1 版本发布流程的后期才出现,在决定采取措施之前没有征求广泛的意见,并且不能推迟到 2.2 版本,否则也会延迟 Cygwin 和 MacOS X 移植。
动机
不同平台的文件系统在是否保留文件名的大小写以及平台 C 库文件打开函数是否坚持区分大小写匹配方面有所不同。
case-preserving case-destroying
+-------------------+------------------+
case-sensitive | most Unix flavors | brrrrrrrrrr |
+-------------------+------------------+
case-insensitive | Windows | some unfortunate |
| MacOSX HFS+ | network schemes |
| Cygwin | |
| | OpenVMS |
+-------------------+------------------+
在左上角的框中,如果创建“fiLe”,它将存储为“fiLe”,只有 open("fiLe")
会打开它(open("file")
不会,其他 14 种变体也不会)。
在右下角的框中,如果创建“fiLe”,无法确定它存储的方式,但最有可能存储为“FILE”,并且 open("FilE")
的 16 种明显变体中的任何一种都可以打开它。
左下角的框是混合的:创建“fiLe”将在平台目录中存储“fiLe”,但打开它时不需要匹配大小写;open("FILe")
的 16 种明显变体中的任何一种都可以工作。
所有这些都不会改变!Python 将继续遵循平台约定,关于创建文件时是否保留大小写以及 open()
是否需要区分大小写匹配。实际上,你应该始终像区分大小写匹配一样编写代码,否则你的程序将不可移植。
提议的是改变 Python “import” 语句的语义,并且仅在左下角的框中进行更改。
当前左下角语义
对 MacOSX HFS+ 和 Cygwin 的支持是 2.1 中的新增功能,因此那里没有任何变化。正在改变的是 Windows 的行为。以下是 Windows 上导入的当前规则。
- 尽管文件系统不区分大小写,但 Python 坚持区分大小写匹配。但这不是左上角框中工作的方式:如果你有两个文件,
FiLe.py
和file.py
在sys.path
上,并且执行import file
那么,如果 Python 首先找到
FiLe.py
,它将引发NameError
。它不会继续查找file.py
;事实上,不可能导入除sys.path
上第一个不区分大小写匹配以外的任何内容,并且只有在第一个不区分大小写匹配的大小写完全匹配的情况下才可能。 - 一个丑陋的例外情况:如果
sys.path
上第一个不区分大小写匹配的文件名完全是大写(FILE.PY
或FILE.PYC
或FILE.PYO
),那么导入将静默地获取它,无论导入语句中使用了哪种大小写混合。这显然是为了满足那些真正适合右下角框的糟糕的老文件系统。但是这个例外情况是 Windows 特有的,原因可能存在也可能不存在。 - 还有一个例外:如果环境变量
PYTHONCASEOK
存在,Python 会静默地获取任何类型的第一個不区分大小写匹配项。
因此,这些 Windows 规则非常复杂,既不匹配 Unix 规则,也不提供对原生文件系统的自然语义。这使得它们难以向 Unix或 Windows 用户解释。尽管如此,它们已经运行多年了,在隔离的情况下,没有充分的理由改变它们。
然而,那是在 MacOSX HFS+ 和 Cygwin 移植出现之前。它们也具有保留大小写的不区分大小写文件系统,但进行移植的人员厌恶 Windows 规则。事实上,一个让 HFS+ 针对导入像 Unix 一样工作的补丁通过了审查并进入了代码库,这顺便也让 Cygwin 也像 Unix 一样工作(但这得到了 Cygwin 人员的无限认可,所以他们当然没有抱怨——他们自己也有一些正在等待审查的补丁来做到这一点,但这些补丁的审查员却犹豫了)。
在更高层面上,我们希望保持 Python 的一致性,通过在所有具有保留大小写的不区分大小写文件系统的平台上遵循相同的规则来实现这一点。
提议的语义
提议的左下角框的新语义
- 如果
PYTHONCASEOK
环境变量存在,则与以前相同:静默地接受任何类型的第一個不区分大小写匹配项;如果未找到,则引发ImportError
。 - 否则,在
sys.path
中搜索第一个区分大小写匹配项;如果未找到,则引发ImportError
。
#B 与 Unix 上使用的规则相同,因此这将提高跨平台可移植性。这是好的。#B 也是 Mac 和 Cygwin 人员想要的规则(并且他们已经多次实现了,这在 PythonLand 中是一个强有力的论据)。它不会导致任何现有的非异常 Windows 导入失败,因为任何现有的非异常 Windows 导入都会在路径中首先找到区分大小写匹配——它仍然会找到。一个异常的 Windows 导入目前会引发 NameError
或 ImportError
,在这种情况下,它仍然会引发,或者在这种情况下会继续搜索,并且要么成功要么引发 ImportError
。
#A 是为了适应安装在 Windows 上的破坏大小写的文件系统,并且可能也会被那些非常喜欢“自然”的 Windows 行为的人使用,他们愿意设置一个环境变量来获得它。我不打算为 Unix 也实现 #A,但这仅仅是因为我不清楚如何有效地做到这一点(我不会为了理论上的纯粹性而减慢 Unix 上的导入速度)。
潜在的损害如下:#2(匹配 ALLCAPS.PY
)被提议删除。破坏大小写的文件系统正在消失,对它们的支撑也很丑陋。我们已经支持(并且将继续支持)PYTHONCASEOK
为它们提供益处,但它们不值得在 2001 年接受多重黑客攻击。
来源:https://github.com/python/peps/blob/main/peps/pep-0235.rst