重新:UnicodeEncodeError:ascii codec无法编码

2024-04-18 17:10:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个XML文件的文件夹,我想解析它。我需要从这些文件的元素中提取文本。它们将被收集并打印到CSV文件中,其中的元素列中列出。

我现在可以为我的一些文件做这个。也就是说,对于我的许多XML文件,这个过程进行得很好,我得到了我想要的输出。执行此操作的代码是:

import os, re, csv, string, operator
import xml.etree.cElementTree as ET
import codecs
def parseEO(doc):
    #getting the basic structure
    tree = ET.ElementTree(file=doc)
    root = tree.getroot()
    agencycodes = []
    rins = []
    titles =[]
    elements = [agencycodes, rins, titles]
    #pulling in the text from the fields
    for elem in tree.iter():
        if elem.tag == "AGENCY_CODE":
            agencycodes.append(int(elem.text))
        elif elem.tag == "RIN":
            rins.append(elem.text)
        elif elem.tag == "TITLE":
            titles.append(elem.text)
    with open('parsetest.csv', 'w') as f:
        writer = csv.writer(f)
        writer.writerows(zip(*elements))


parseEO('EO_file.xml')     

但是,在输入文件的某些版本上,我得到了一个臭名昭著的错误:

'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128)

完整的回溯是:

    ---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-15-28d095d44f02> in <module>()
----> 1 execfile(r'/parsingtest.py') # PYTHON-MODE

/Users/ian/Desktop/parsingtest.py in <module>()
     91         writer.writerows(zip(*elements))
     92 
---> 93 parseEO('/EO_file.xml')
     94 
     95 

/parsingtest.py in parseEO(doc)
     89     with open('parsetest.csv', 'w') as f:
     90         writer = csv.writer(f)
---> 91         writer.writerows(zip(*elements))
     92 
     93 parseEO('/EO_file.xml')
UnicodeEncodeError: 'ascii' codec can't encode character u'\x97' in position 32: ordinal not in range(128)

通过阅读其他线程,我非常确信问题出在正在使用的编解码器上(而且,你知道,这个错误也很明显)。然而,我读过的解决方案并没有帮助我(强调是因为我知道我是问题的根源,而不是人们过去的回答方式)。

有几个代表(例如:this onethis onethis one)没有直接处理ElementTree,我不知道如何将解决方案转换为我正在做的事情。

其他处理ElementTree的解决方案(例如:this onethis one)要么使用短字符串(这里是第一个链接),要么使用ElementTree中的.tostring/.fromstring方法,而我没有。(当然,也许我应该这么做。)

我试过但没用的东西:

  1. 我试图通过UTF-8编码引入文件:

    infile = codecs.open('/EO_file.xml', encoding="utf-8")
    parseEO(infile)
    

    但是我认为ElementTree进程已经理解它是UTF-8(在我拥有的所有XML文件的第一行中都有说明),所以这不仅不正确,而且实际上是一次又一次的冗余错误。

  2. 我试图在循环中声明一个编码过程,替换:

    tree = ET.ElementTree(file=doc)
    

    parser = ET.XMLParser(encoding="utf-8")
    tree = ET.parse(doc, parser=parser)
    

    在上面的循环中确实有效。这对我也没用。以前工作过的文件仍然工作,创建错误的文件仍然创建错误。

有很多其他的随机尝试,但我不会吹嘘这一点。

所以,虽然我认为我所拥有的代码既低效又不利于良好的编程风格,但它确实满足了我对几个文件的要求。我试着去理解是否有一个我不知道的参数丢失了,我是否应该预先处理文件(我还没有确定有问题的字符在哪里,但是我知道u'\x97转换成某种控制字符),或者其他选项。


Tags: 文件csvintreedoc错误xmlthis
2条回答

听起来xml文件中的某个地方有一个unicode字符。Unicode不同于编码为utf8的字符串。

python2.7csv库不支持unicode字符,因此在将数据转储到csv文件之前,必须通过对其进行编码的函数运行数据。

def normalize(s):
    if type(s) == unicode: 
        return s.encode('utf8', 'ignore')
    else:
        return str(s)

所以你的代码如下:

for elem in tree.iter():
    if elem.tag == "AGENCY_CODE":
        agencycodes.append(int(elem.text))
    elif elem.tag == "RIN":
        rins.append(normalize(elem.text))
    elif elem.tag == "TITLE":
        titles.append(normalize(elem.text))

您正在分析XML;XML API将unicode值交给您。然后尝试将unicode数据写入CSV文件而不首先对其进行编码。然后,Python尝试为您编码,但失败了。您可以在回溯中看到这一点,失败的是.writerows()调用,错误告诉您编码失败,而不是解码(解析XML)。

您需要选择一种编码,然后在写入之前对数据进行编码:

for elem in tree.iter():
    if elem.tag == "AGENCY_CODE":
        agencycodes.append(int(elem.text))
    elif elem.tag == "RIN":
        rins.append(elem.text.encode('utf8'))
    elif elem.tag == "TITLE":
        titles.append(elem.text.encode('utf8'))

我使用UTF8编码是因为它可以处理任何Unicode代码点,但您需要做出自己的明确选择。

相关问题 更多 >