【问题标题】:(Python) Write string to CSV with UTF-8 Encoding(Python) 使用 UTF-8 编码将字符串写入 CSV
【发布时间】:2023-03-27 05:34:01
【问题描述】:

我在数据库中有数据,我想将其导出为 CSV 文件。 数据为日文,为了进一步使用,我需要将其编码为 UTF-8

这是我获取数据并写入 CSV 文件的脚本

import mysql.connector
from mysql.connector import errorcode

import sys
import csv

query = 'SELECT * FROM `images-data`'

try:
    cnx = mysql.connector.connect(user='root', password='1234',
                                 host='127.0.0.1',
                                 database='sotsuken-test-db')
    cur=cnx.cursor()
    cur.execute(query)
    result=cur.fetchall()

    c = csv.writer(open("db-data.csv","w"))
    for row in result:
        c.writerow(row)



except mysql.connector.Error as err:
    if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
        print("Something is wrong with your user name or password")
    elif err.errno == errorcode.ER_BAD_DB_ERROR:
        print("Database does not exist")
    else:
        print(err)
else:
    cnx.close()

我可以创建 CSV 文件,数据以 UTF-8 格式导出,但我的 CSV 文件的数据是这样的:

1,b'\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88\xe3\x81\xa7\xe3\x81\x94\xe3\x81\x8a\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99'

在我的研究中,我发现我的数据是用字节对象写入的(可能我在这里错了)。我需要在没有b''的情况下以UTF-8 写入数据

我知道我可以使用decode("UTF-8") 将其添加到字符串中,但我无法将其应用于csv.writerow

你能给我一些建议吗?

【问题讨论】:

  • 为什么不使用 csv.DictWriter 命令,您可以解码('UTF-8')您的单个单元格值并使用 DictWriter 您可以写入 csv 文件中的特定列
  • 感谢您提出了一个关于新问题/关于主题/mvce 的所有指南的漂亮、简洁、写得很好的问题
  • @SuryaTej DictWriter 如何比writer 更好地解决这个问题?当然,如果您知道自己的列是什么,出于其他 的原因会更好,但这并不会改变其中一些列是bytes 的事实。
  • 附带说明,您实际上不需要在这里执行fetchall。您可以只迭代for row in cur:,并且游标应该一次给您一行,在内存中缓冲尽可能多的行,因为它认为最有效,而不是无论如何都将它们全部读入内存。此外,不关闭您为写入而打开的文件通常是个坏主意,无论是使用close() 调用还是with 语句。

标签: python python-3.x csv utf-8 export-to-csv


【解决方案1】:

csv.writer.writerow 只是获取您所拥有的任何内容的列表,1 在每个元素上调用 str,然后将它们放在一行 CSV 中。

所以,如果你得到的是bytes 对象,那么它将调用str 并获取类似b'\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88\xe3\x81\xa7\xe3\x81\x94\xe3\x81\x8a\xe3\x81\x96\xe3\x81\x84\xe3\x81\xbe\xe3\x81\x99' 的字符串。

解决办法是给它字符串。


最简单的方法是解码bytes

我知道我可以使用decode("UTF-8") 将其添加到字符串中,但我无法将其应用于csv.writerow

当然可以。我不知道你的专栏是什么,所以我会自己编一个例子:

for image_id, image_name in result:
    c.writerow([image_id, image_name.decode('UTF-8')])

这就是它的全部内容。


如果您的代码完全不知道数据库中的列是什么,该怎么办?好吧,在那种情况下,你必须变得聪明一点。只要我们知道所有bytes 列都是伪装成UTF-8 的真正Unicode 文本,您就可以打开类型:

for row in result:
    textrow = [col.decode('UTF-8') if isinstance(col, bytes) else col for col in row]
    csv.writerow(textrow)

这有点难看,但是从您不知道列是什么的数据库中读取 * 本质上是一个难看的问题。


但是,可能有更好的解决方案。

MySQL 连接器/Python 默认将所有 CHARTEXT 和类似列转换为 Unicode str 值。2BINARYBLOB 和类似列是始终返回为bytes

如果此列用于表示 Unicode 文本,请将其设置为文本类型,而不是数据库中的二进制类型。那么你首先就不会有问题了——在这个脚本中,或者在任何其他工具中。


1。实际上,根据文档,使用除字符串和数字之外的任何内容的列表来调用它似乎是非法的。但实际上,它需要任何东西。它只是对字符串和数字以外的任何类型都没有做任何非常有用的...

2。也就是说,除非您在 connect 调用中显式传递 use_unicode=False 或在其他地方类似地设置它。

【讨论】:

    猜你喜欢
    • 2011-09-06
    • 2011-04-21
    • 2014-07-01
    • 2011-07-22
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 2021-04-18
    • 2011-08-09
    相关资源
    最近更新 更多