如何修复不一致的UnicodeEncodeError读取/打开文件

时间:2019-04-23 08:35:57

标签: python python-2.7 python-unicode

我最近选择了Python,并且继承了一些Python 2.7代码,在这些代码中我试图解决一些异常。对于每个命令行参数(目录名称),主代码调用导入的功能来在那里处理一些XML文件,然后所讨论的代码通过从“匹配”文件中读取行并设置字典来映射“匹配”字符串与文件中的行号(以后将用于标记XML中找到的字符串匹配项)。

匹配文件本身永远不会更改;它总是从磁盘加载相同的文件。它采用UTF-8格式,大约12,000行,其中100行包含非ASCII字符。在大多数情况下,这种加载不会发生任何故障。但是,有时,此代码会引发异常:“ UnicodeEncodeError:'ascii'编解码器无法在位置12编码字符u'\ xf3':序数不在range(128)中”。字符代码和位置也相差很大。我已经验证了读取的文件名和文件内容不会改变。只是偶尔,Python决定对通常可以读取的相同数据抛出异常!

我注意到,这些异常似乎总是在导入的模块报告处理内部列表的错误之后发生,但是如何使其他模块突然对以前可以接受的数据抛出异常却是一个谜。

这是我最初看到的错误:

ProcessXML - entry 52 bad list string, skipping...
class StrMatcher.__init__ called
Traceback (most recent call last):
  File "/home/tests/my_main.py", line 19, in my_main
    obj = StrMatcher("/home/tests/match_strings.txt")
  File "/home/tests/my_common.py", line 20, in __init__
    for line in f:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 12: ordinal not in range(128)

通过此代码:

class StrMatcher:
    def __init__(self, matches_file):
        print("StrMatcher.__init__ called")
        self.line_numbers = {}
        i = 1
        with open(matches_file, 'r') as f:
            for line in f:
                self.line_numbers[line.strip()] = i
                i += 1

(与其他有关Python Unicode错误的问题不同,尽管总是处理完全相同的数据,该错误也会不一致发生。)

我打印出“ i”,并且看到从文件中读取了最后一行之后发生了错误(因此大概是在尝试处理EOF)。我打印出“行”的类型,并注意到它是“ ”,所以我尝试更改“打开”行:

        with io.open(matches_file, mode='r', encoding="utf-8") as f:

这会将'line'更改为“ ”,并且还更改了错误输出(对于那些有错误的情况;否则,它和以前的代码一样工作):

ProcessXML - entry 52 bad list string, skipping...
class StrMatcher.__init__ called
Traceback (most recent call last):
  File "/home/tests/my_main.py", line 19, in my_main
    obj = StrMatcher("/home/tests/match_strings.txt")
  File "/home/tests/my_common.py", line 19, in __init__
    with io.open(matches_file, mode='r', encoding="utf-8") as f:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 12: ordinal not in range(128)

表现出“ ProcessXML”错误的不同输入目录(和/或同一目录可能运行不同,不确定)会导致异常字符/范围跳转,例如

UnicodeEncodeError: 'ascii' codec can't encode character u'\xfa' in position 43: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 91: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u200b' in position 52: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 48-50: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 37: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 32: ordinal not in range(128)

这是怎么回事?为何“ ascii”编解码器尝试编码,为什么?尤其是在以“ utf-8”模式打开文件时?

我认为在错误情况下导入的模块会无意中更改了某些状态,但是令我惊讶的是,当可以打开完全相同的文件/数据时,任何使读取行或在另一个模块中打开文件的事情都可能引发UnicodeEncodeError并在其他情况下通过相同的代码成功读取!它是Python 2.7错误吗?还是“开放”代码中的某些全局状态?还是...?

0 个答案:

没有答案