首先,关于ElementTree的所有内容在这里可能都不相关.尝试仅枚举f = open(filename,encoding =’utf-8′)返回的文件,您可能会遇到相同的错误.
如果是这样,解决方案是覆盖默认的编码错误处理程序,如the docs中所述:
errors is an optional string that specifies how encoding and decoding errors are to be handled–this cannot be used in binary mode. Pass ‘strict’ to raise a ValueError exception if there is an encoding error (the default of None has the same effect), or pass ‘ignore’ to ignore errors. (Note that ignoring encoding errors can lead to data loss.) ‘replace’ causes a replacement marker (such as ‘?’) to be inserted where there is malformed data. When writing, ‘xmlcharrefreplace’ (replace with the appropriate XML character reference) or ‘backslashreplace’ (replace with backslashed escape sequences) can be used. Any other error handling name that has been registered with codecs.register_error() is also valid.
因此,您可以这样做:
f = open(filename, encoding='utf-8', errors='replace')
这符合您的第二优先级-无效字符将替换为’?’.
无法满足您的优先级,因为无法表示“不必要有效的Unicode字符串”.根据定义,Unicode字符串是Unicode代码点的序列,这就是Python处理str类型的方式.如果您有无效的UTF-8,并且想将其转换为字符串,则需要指定应如何将其转换为字符串,这就是错误的原因.
或者,您可以以二进制模式打开文件,并将UTF-8单独作为字节对象,而不是尝试将其转换为Unicode str对象,但是您只能使用与字节对象一起使用的API. (我相信ElementTree的lxml实现实际上可以做到这一点,但是内置的实现不能,但是请不要在上面引用我的意思.)但是即使您这样做了,也不会让您走得太远,因为XML代码本身将尝试解释无效的UTF-8,然后它需要知道您要对错误执行什么操作,而且通常很难指定,因为它的范围更广.
最后一点:
Since the error occurs in between for loop iterations, the only place I can wrap a try block is outside the for loop, which would mean I cannot continue to the next XML element.
好吧,实际上您不必使用for循环;您可以将其转换为带有显式下一个调用的while循环.每当您需要执行此操作时,通常都表明您做错了事情,但有时这表明您正在处理损坏的库,这是唯一可用的解决方法.
这个:
for (event, elem) in xmlit: # line 26
doStuffWith(event, elem)
有效等效于:
while True:
try:
event, elem = next(xmlit)
except StopIteration:
break
doStuffWith(event, elem)
现在,有一个明显的地方可以尝试一下-尽管您甚至不需要.您可以仅将另一个附加到现有的try上.
问题是,您打算在这里做什么?不能保证迭代器在引发异常后将能够继续.实际上,创建迭代器的所有最简单方法都将无法实现.您可以自己测试在这种情况下是否正确.
在极少数情况下,当您需要这样做并且确实有帮助时,您可能希望将其包装起来.像这样:
def skip_exceptions(it):
while True:
try:
yield next(it)
except StopIteration:
raise
except Exception as e:
logging.info('Skipping iteration because of exception {}'.format(e))
然后,您只需执行以下操作:
for (event, elem) in skip_exceptions(xmlit):
doStuffWith(event, elem)