python - 如何在 Python 中将特殊字符写入 CSV?

标签 python

尝试用 Python 将数据写入 CSV 时,我收到以下错误。

File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/csv.py", line 150, in writerows
UnicodeEncodeError: 'ascii' codec can't encode character u'\xd3' in position 0: ordinal not in range(128)

这是我尝试写入 CSV 的字典示例:

{'Field1': 'Blah \xc3\x93 D\xc3\xa1blah', 'Field2': u'\xd3', 'Field3': u'Blah', 'Field4': u'D\xe1blah'}

我知道您不能使用 Python 将 unicode 写入 CSV,但我无法弄清楚要转换成什么以及如何转换它。

编辑:这是我试过的方法。 dictList 是从另一个 CSV 中获取的字典列表。

WANTED_HEADERS = ['First Name',
                  'Last Name',
                  'Date',
                  'ID']

def utf8ify(d):
  return dict((str(k).encode('utf-8'), str(v).encode('utf-8')) for k, v in d.iteritems())

def ListToCSVWithHeaders(data_list, output_file_name, headers):
output_file = open(output_file_name, 'w')
header_row = {}
to_append = []
for entry in data_list:
  to_append.append(utf8ify(entry))
  for key in entry.keys():
    if key not in headers:
      headers.append(key)
      print 'KEY APPENDED: ' + key
for header in headers:
  header_row[header] = header
data = [header_row]
data.extend(to_append)
data_writer = csv.DictWriter(output_file, headers)
data_writer.writerows(data)
print str(len(data)) + ' rows written'

ListToCSVWithHeaders(dictList, 'output.csv', WANTED_HEADERS)

这是我在运行时收到的错误。

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 7: ordinal not in range(128)

最佳答案

您不能将 Unicode 写入 CSV 中……但您可以写入恰好是 UTF-8(或 Latin-1,或几乎任何其他编码*)编码 Unicode 的字节。 The docs明确说明这一点,并建议如何处理它:

Note: This version of the csv module doesn’t support Unicode input. Also, there are currently some issues regarding ASCII NUL characters. Accordingly, all input should be UTF-8 or printable ASCII to be safe; see the examples in section Examples. These restrictions will be removed in the future.

Examples section展示如何处理这个问题,提供让您读写的包装器 unicode对象,自动为您编码/解码 UTF-8。如果您使用不同的字符集(例如,因为您计划将其传递给需要 cp1252 编码的 CSV 的 Excel VBscript),只需替换 'utf-8'视情况而定。


示例代码做了一些花哨的步法来确保 csv模块本身只需处理 UTF-8,而文件可以采用不同的编解码器。这是处理可能混淆 csv 模块的编解码器的好方法。但看起来您只是在寻找 Latin-1(或像 cp1252 这样的 Latin-1 扩展字符集),或者甚至可能是 UTF-8 本身。在这种情况下,您可以只使用一个快速且肮脏的解决方案,如下所示:

w.writerows(mydata)

...你可以像这样做一些骇人听闻的事情:

def utf8ify(d):
    return dict((k.encode('utf-8'), v.encode('utf-8')) for k, v in d.iteritems())

w.writerows(utf8ify(d))

根据您尝试写入的值,您可能需要更改以上内容。例如,如果您在原始字典中有 Latin-1 字符串,您将需要如下内容:

k.decode('latin-1').encode('utf-8'), …

如果您不知道自己要写的东西的种类……好吧,您无法采用快速而肮脏的解决方案。


在您编辑的版本中,您正在以这种方式使用快速和肮脏的解决方案:

def utf8ify(d):
  return dict((str(k).encode('utf-8'), str(v).encode('utf-8')) for k, v in d.iteritems())

…您传递的值似乎是 unicode 的混合体类似 u'\xd3' 的字符串我认为是 UTF-8 编码的 str字节串,如 'Blah \xc3\x93 D\xc3\xa1blah' .那里可能还有一些数字或其他东西,或者你只是小心点。

无论如何,那是行不通的; UTF-8 编码的字符串将通过 str不变,解码为sys.getdefaultencoding() , 并重新编码为 UTF-8,而 Unicode 字符串将使用默认编码进行编码,使用默认编码解码,然后使用 UTF-8 重新编码。

如果这是你的实际数据,代码将是这样的:

def utf8ify_s(s):
    if isinstance(s, unicode):
        return s.encode('utf-8')
    else:
        return str(s)

这将编码 unicode字符串,假设 str字符串已经是 UTF-8 并通过 str 传递它们(这将使它们保持不变),并通过调用 str 将数字等转换为字符串。 (这对任何内置类型都适用,只要您编写的自定义类型的 str 是纯 ASCII 或 UTF-8,它们也适用)。然后,而不是 str(…).encode('utf-8')对于每个 kv ,调用这个函数:

def utf8ify(d):
    return dict(utf8ify_s(k): utf8ify_s(v) for k, v in d.iteritems())

与此同时,我强烈建议您通读 Unicode HOWTO ,以及您需要的任何其他内容,以了解此处实际发生的情况,而不是仅仅尝试修改您的代码直到它看起来可以工作。


* 实际的规则是这样的:没有嵌入的 NUL 字节(所以 UTF-16 不存在),没有可以跨越多行的持久状态(所以一些东亚编码不存在),并且没有“代理”风格与引号字符的字节匹配的部分字符字节。如果您不确定……请使用高级转换器并通过 UTF-8。

关于python - 如何在 Python 中将特殊字符写入 CSV?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18069407/

相关文章:

python - 用于 Transformer DNN 模型的基于时间序列的数据的位置编码

python - 使用 python ibPy 库获取你的投资组合的位置

python - 无法登录 Django 中的管理站点

python - 为什么 "Models aren' t 已加载”?

python Pandas : Sorting Columns

python - Cassandra 。默认列值

python - 在行延续中混合普通字符串和 f 字符串

python - 将数组写入文本文件,每行中具有最大元素数量

python - 用Python下载的图片损坏了?

python - 如何将 PyCharm 与 Google 计算引擎一起使用