在python中读取一个unicode文件,它以与python源相同的方式声明其编码

cir*_*uin 9 python unicode

我想写一个python程序,它读取包含unicode文本的文件.这些文件通常用UTF-8编码,但可能不是; 如果不是,则将在文件的开头显式声明备用编码.更确切地说,它将使用与Python本身使用的完全相同的规则来声明,以允许Python源代码具有显式声明的编码(如在PEP 0263中,请参阅https://www.python.org/dev/peps/pep- 0263 /更多细节).为了清楚起见,正在处理的文件实际上并不是python源,但它们确实使用相同的规则声明了它们的编码(当不是UTF-8时).

如果在打开文件之前知道文件的编码,Python提供了一种非常简单的方法来自动解码文件:codecs.open命令; 例如,有人可能会:

import codecs
f = codecs.open('unicode.rst', encoding='utf-8')
for line in f:
    print repr(line)
Run Code Online (Sandbox Code Playgroud)

line我们进入循环的每一个都是一个unicode字符串.是否有一个Python库做类似的事情,但根据上面的规则选择编码(我认为这是Python 3.0的规则)?(例如,Python是否公开了'使用自我声明编码的'读取文件'来读取语言的来源?)如果没有,那么实现所需效果的最简单方法是什么?

一种想法是使用通常打开文件open,读取前两行,将它们解释为UTF-8,使用PEP中的regexp查找编码声明,如果找到一个使用声明的编码开始解码所有后续行.为了确保这一点,我们需要知道,对于Python在Python源代码中允许的所有编码,通常的Python readline会正确地将文件拆分成行 - 也就是说,我们需要知道Python允许的所有编码Python源代码,字节串'\n'总是真正意味着换行符,并不是编码另一个字符的多字节序列的一部分.(事实上​​我也需要担心'\ r \n'.)有人知道这是否属实?文档不是很具体.

另一个想法是查看Python源代码.有谁知道在Python源代码中源代码编码处理的位置是什么?

sam*_*ias 7

您应该能够在Python中使用自己的解码器.如果您只支持8位编码,这些编码是ASCII的超集,则下面的代码应该按原样运行.

如果您需要支持像UTF-16这样的 2字节编码,则需要\x00c\x00o..根据字节顺序标记来增加模式以匹配或反向.首先,生成一些宣传其编码的测试文件:

import codecs, sys
for encoding in ('utf-8', 'cp1252'):
    out = codecs.open('%s.txt' % encoding, 'w', encoding)
    out.write('# coding = %s\n' % encoding)
    out.write(u'\u201chello se\u00f1nor\u201d')
    out.close()
Run Code Online (Sandbox Code Playgroud)

然后写解码器:

import codecs, re

def open_detect(path):
    fin = open(path, 'rb')
    prefix = fin.read(80)
    encs = re.findall('#\s*coding\s*=\s*([\w\d\-]+)\s+', prefix)
    encoding = encs[0] if encs else 'utf-8'
    fin.seek(0)
    return codecs.EncodedFile(fin, 'utf-8', encoding)

for path in ('utf-8.txt','cp1252.txt'):
    fin = open_detect(path)
    print repr(fin.readlines())
Run Code Online (Sandbox Code Playgroud)

输出:

['# coding = utf-8\n', '\xe2\x80\x9chello se\xc3\xb1nor\xe2\x80\x9d']
['# coding = cp1252\n', '\xe2\x80\x9chello se\xc3\xb1nor\xe2\x80\x9d']
Run Code Online (Sandbox Code Playgroud)