【问题标题】:Processing non-UTF-8 Posix filenames using Python pathlib?使用 Python pathlib 处理非 UTF-8 Posix 文件名?
【发布时间】:2018-01-25 05:27:12
【问题描述】:

我正在尝试使用在 Python 3.4+ 中成为标准库一部分的 pathlib 模块来查找和操作文件路径。尽管它是对 os.path 样式函数的改进,能够以面向对象的方式处理路径,但我在处理 Posix 文件系统上一些更奇特的文件名时遇到了麻烦;特别是名称中包含无法解码为 UTF-8 的字节的文件:

>>> pathlib.PosixPath(b'\xe9')

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/pathlib.py", line 969, in __new__
    self = cls._from_parts(args, init=False)
  File "/usr/lib/python3.5/pathlib.py", line 651, in _from_parts
    drv, root, parts = self._parse_args(args)
  File "/usr/lib/python3.5/pathlib.py", line 643, in _parse_args
    % type(a))
TypeError: argument should be a path or str object, not <class 'bytes'>

>>> b'\xe9'.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 0: unexpected end of data

问题在于,在 Posix 文件系统上,这样的文件可以存在,我希望能够在我的应用程序中处理任何文件系统有效的文件名,而不是导致错误和/或可预测的行为。

我可以通过使用父目录的 .iterdir() 方法在目录中获取此类文件的 PosixPath 对象。但是我还没有找到一种方法从作为“字节”类型变量提供的完整路径中获取它,当从完全支持所有文件系统有效的原始字节值的另一个源加载路径时,这是很难避免的(例如数据库或包含 nul 分隔路径的文件)。

有没有我不知道的方法来做到这一点?或者,如果真的不可能:这是设计使然,还是认为标准库中的缺陷可能需要报告错误?

我确实找到了related bug report,但该问题涉及文档错误地提到允许使用“字节”类的参数。

【问题讨论】:

    标签: python python-3.x utf-8 posix pathlib


    【解决方案1】:

    我想你可以这样得到你想要的:

    import os
    PosixPath(os.fsdecode(b'\xe9'))
    

    演示:

    >>> import os, pathlib
    >>> b = b'\xe9'
    >>> p = pathlib.Path(os.fsdecode(b))
    >>> p.exists()
    False
    >>> with open(b, mode='w') as f:
    ...     f.write('wacky filename')
    ...     
    >>> p.exists()
    True
    >>> p.read_bytes()
    b'wacky filename'
    >>> os.listdir(b'.')
    [b'\xe9']
    

    【讨论】:

    • 谢谢。尽管我在 Python 3 讨论中顺便看到过“代理编码”,但我不知道它允许将任何原始字节值表示为 Unicode 代码点,并且该机制为我遇到的问题提供了可行的解决方案。我仍然觉得能够使用真正的“字节”将是一种语义上更有意义的方法(原始数据毕竟不是 真的 Unicode)。从好的方面来说,了解这个技巧可能会让我解决类似的问题情况并帮助减少对“原始字节”类型持久存储的需求。
    • 在这种情况下,我不同意的实际上是 POSIX。我们可以将具有不同编码的文件名放在同一个目录中,这很混乱。这可能是 Windows 近来比 Linux 做得更好的少数几件事之一。
    • 我同意,将文件名作为原始字节是一种相当过时的方法(我猜是由 Posix 背后的悠久历史解释的),因为整个在线世界几乎已经确定了 Unicode / UTF-8 .听起来,Python 使用代理对的方法实际上可能为 Linux/UNIX 系统提供了一种途径,允许在保持向后兼容性的同时迁移到 Unicode。再说一次,人们可能已经在努力了……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多