【问题标题】:Again: UnicodeEncodeError: ascii codec can't encode再次:UnicodeEncodeError:ascii 编解码器无法编码
【发布时间】:2023-04-06 09:37:01
【问题描述】:

我有一个要解析的 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)

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

几个repsonses(例如: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 转换为某种控制字符)或其他选项。

【问题讨论】:

    标签: python python-2.7 ascii codec elementtree


    【解决方案1】:

    您正在解析 XML; XML API 为您提供unicode 值。然后,您尝试将 unicode 数据写入 CSV 文件而不先对其进行编码。然后 Python 会尝试为您编码,但失败了。您可以在回溯中看到这一点,这是 .writerows() 调用失败,错误告诉您 encoding 失败,而不是解码(解析 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 代码点,但您需要做出自己的明确选择。

    【讨论】:

      【解决方案2】:

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

      python2.7 csv 库不支持 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))
      

      【讨论】:

      • 非常感谢。 Martijn 的建议是我尝试的第一个建议,它解决了我的直接问题。这看起来像是我可以在下一轮学习的东西。非常感谢您花时间发帖。
      • 我花了很多时间(不幸的是)尝试调试 unicode 错误。我花了一段时间才把我的想法包起来!乐于助人!
      • 不要使用type(s) == unicode;请改用isinstance(s, unicode)
      猜你喜欢
      • 1970-01-01
      • 2018-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 2017-03-01
      • 2013-08-01
      • 2015-11-21
      相关资源
      最近更新 更多