codecs.open(utf-8) 无法读取纯 ASCII 文件

2023-11-24

我有一个纯 ASCII 文件。当我尝试用以下命令打开它时codecs.open(..., "utf-8"),我无法读取单个字符。 ASCII 是 UTF-8 的子集,为什么不能codecs以UTF-8模式打开这样的文件?

# test.py

import codecs

f = codecs.open("test.py", "r", "utf-8")

# ASCII is supposed to be a subset of UTF-8:
# http://www.fileformat.info/info/unicode/utf8.htm

assert len(f.read(1)) == 1 # OK
f.readline()
c = f.read(1)
print len(c)
print "'%s'" % c
assert len(c) == 1 # fails

# max% p test.py
# 63
# '
# import codecs
#
# f = codecs.open("test.py", "r", "utf-8")
#
# # ASC'
# Traceback (most recent call last):
#   File "test.py", line 15, in <module>
#     assert len(c) == 1 # fails
# AssertionError
# max%

system:

Linux max 4.4.0-89-generic #112~14.04.1-Ubuntu SMP Tue Aug 1 22:08:32 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

当然,它适用于常规open。如果我删除它也有效"utf-8"选项。还有什么63意思是?就像第三行的中间一样。我不明白。


发现你的问题:

当传递编码时,codecs.open返回一个StreamReaderWriter,这实际上只是 (not的子类;这是一种“组成”关系,而不是继承)StreamReader and StreamWriter。问题是:

  1. StreamReaderWriter提供“正常”read方法(也就是说,它需要一个size参数就是这样)
  2. 它委托给内部StreamReader.read method,其中sizeargument 只是关于要读取的字节数的提示,而不是限制;这second争论,chars,是一个严格的限制器,但是StreamReaderWriter从不传递该论点(它不接受它)
  3. When size暗示,但不限制使用chars, if StreamReader有缓冲数据,并且它足够大以匹配size hint StreamReader.read盲目地返回缓冲区的内容,而不是根据缓冲区以任何方式限制它size提示(毕竟只是chars强加一个maximum返回尺寸)

的 APIStreamReader.read和的意义size/chars因为 API 是这里唯一有记录的东西;事实是codecs.open回报StreamReaderWriter不是契约性的,也不是事实StreamReaderWriter wraps StreamReader,我刚刚用过ipython's ??魔法阅读源代码codecs模块来验证此行为。但无论是否有记录,这就是它正在做的事情(请随意阅读源代码StreamReaderWriter,都是Python级别的,所以很简单)。

最好的解决方案是切换到io.open,在每个标准情况下都更快、更正确(codecs.open支持不相互转换的怪异编解码器bytes [Py2 str] and str [Py2 unicode],而是处理str to str or bytes to bytes编码,但这是一个极其有限的用例;大多数时候,你在之间转换bytes and str)。您所需要做的就是导入io代替codecs,并更改codecs.open线路至:

f = io.open("test.py", encoding="utf-8")

其余代码可以保持不变(并且启动时可能会运行得更快)。

作为替代方案,您可以显式绕过StreamReaderWriter得到StreamReader's read方法并直接传递限制参数,例如改变:

c = f.read(1)

to:

# Pass second, character limiting argument after size hint
c = f.reader.read(6, 1)  # 6 is sort of arbitrary; should ensure a full char read in one go

我猜测Python 错误 #8260,其中涵盖了混合readline and read on codecs.open创建的文件对象,适用于此处,正式地,它是“已修复”,但如果您阅读注释,则修复尚未完成(鉴于已记录的 API,可能无法完成);任意奇怪的组合read and readline就能打破它。

再次,只需使用io.open;只要您使用的是 Python 2.6 或更高版本,它就可用,而且效果明显更好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

codecs.open(utf-8) 无法读取纯 ASCII 文件 的相关文章

随机推荐