【问题标题】:Parsing non-ASCII characters in Python 3在 Python 3 中解析非 ASCII 字符
【发布时间】:2016-05-22 17:55:08
【问题描述】:

我正在尝试从包含 é、Ä 等字符的文件中读取数据。我正在使用 numpy.loadtxt() 但我收到了 UnicodeDecodeErrors,因为解码器无法解析它们。我的首要任务是尽可能保留这些角色,但如果没有,我不介意更换它们。有什么建议吗?

【问题讨论】:

  • loadtxt(和genfromtxt)使用字节串(用于 Py2 兼容性等)。编写自己的阅读器或使用csv 模块可能比与之抗争更简单。确保您的 structured array dtype 使用 unicode 字符串类型。
  • csv 模块肯定会派上用场,但列是制表符分隔的。当您说“编写我自己的阅读器”时,您的意思是基于标准的 Python 文件 I/O?

标签: python-3.x numpy non-ascii-characters


【解决方案1】:

除了@unutbu 找到的链接(使用genfromtxt 中的解码/编码),这里是一个直接文件阅读器的速写:

示例文件 (utf8)

é, Ä
é, Ä
é, Ä

readlines, split, and pass through np.array:

In [327]: fn='uni_csv.txt'
In [328]: with open(fn) as f:lines=f.readlines()
In [329]: lines
Out[329]: ['é, Ä\n', 'é, Ä\n', 'é, Ä\n']
...
In [331]: [l.strip().split(',') for l in lines]
Out[331]: [['é', ' Ä'], ['é', ' Ä'], ['é', ' Ä']]
In [332]: np.array([l.strip().split(',') for l in lines])
Out[332]: 
array([['é', ' Ä'],
       ['é', ' Ä'],
       ['é', ' Ä']], 
      dtype='<U2')

我不认为tab 分隔存在问题(除了我的文本编辑器设置为用空格替换制表符)。

对于混合数据类型,我需要添加一个tuple 转换(结构化数组定义需要一个元组列表):

In [343]: with open(fn) as f:lines=f.readlines()
In [344]: dt=np.dtype([('int',int),('é','|U2'),('Ä','U5')])
In [345]: np.array([tuple(l.strip().split(',')) for l in lines], dt)
Out[345]: 
array([(1, ' é', ' Ä'), (2, ' é', ' Ä'), (3, ' é', ' Ä')], 
      dtype=[('int', '<i4'), ('é', '<U2'), ('Ä', '<U5')])

(我在文本文件中添加了一个整数列)


实际上loadtxt 也不会阻塞这个文件和dtype;它只是加载错误的字符串。

In [349]: np.loadtxt('uni_csv.txt',dtype=dt, delimiter=',')
Out[349]: 
array([(1, "b'", "b' \\x"), (2, "b'", "b' \\x"), (3, "b'", "b' \\x")], 
      dtype=[('int', '<i4'), ('é', '<U2'), ('Ä', '<U5')])

【讨论】:

  • 解释器吐出以下问题UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 6908: ordinal not in range(128) 这意味着它仍然无法读取文件中的某些字符。我的问题是源文件是用 UTF-8 编码的。从理论上讲,它不应该引起这样的问题,对吧?
  • 我不确定你的代码在哪里引发了这个错误。
  • 我也不是(它可能会在文本的某处找到另一个非 ASCII 字符),但显然用open("outfile.sql", encoding="utf-8") 打开文件并将每一行附加到列表中以进行进一步处理工作。在我看来,这是一个笨拙的解决方法,但它必须这样做。
  • 不过,我赞成您对处理不同数据类型的回答,谢谢。
  • 您的答案通过添加可选的encoding= 起作用。换句话说,对文件处理程序的初始调用将是:with open(fn, encoding="utf-8") as f:lines=f.readlines()
猜你喜欢
  • 2019-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 2018-08-09
  • 2016-02-10
  • 1970-01-01
相关资源
最近更新 更多