0

我有一个使用 xlwt/xlrd 处理 excel 文件的 python 脚本。在我的脚本的开头,我有以下代码:

#if you got a csv in parameters, convert it to an xls file
if '.csv' in sys.argv[1]:
    #name of new file after conversion is finished
    name = sys.argv[1]
    csvfile = open(sys.argv[1], 'rb')
    try:
        #extract data from .csv
        csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|')
        csvData = list(csv.reader(open(name, 'rb')))
        # write to a xls file
        outFile = xlwt.Wrokbook()
        newSheet = outFile.add_sheet('Sheet 1')
        # traverse over 2d array to write each individual cell
        for row in range(len(csvData)):
            for col in range(len(csvData[0])):
                newSheet.write(row, col, csvData[row][col].encode('utf8'))
         name = name[:-4] + ".xls" #change extension of file
         outFile.save(name)
         wb = open_workbook(name)
    finally:
         csvfile.close()

这给出了错误

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

就行 outFile.save(name)

到目前为止,我发现的唯一有用的东西是UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 1,但我的终端使用 utf8 作为其编码。

编辑:完全忘记提及这一点,很抱歉。

我相信带有 .encode 的行以某种方式导致了错误,但我想不出如何。我最初没有.encode,然后我添加了.encode('utf8'),还尝试了.encode('utf-8')和unicode(string,'utf8')。我不确定还有什么方法可以解决这个问题。

编辑:我尝试了布赖恩的建议,但无济于事。此外,我尝试了 codecs.open 建议,还尝试在创建工作簿时指定编码。这些都不会改变错误。我尝试过的唯一改变错误的方法是在 newSheet.write 的行上添加 .encode。没有它,我得到:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2013' in position 44: ordinal no in range(128)

有了它,我得到:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 44: ordinal not in range(128)
4

3 回答 3

1

根据文档

csv 模块不直接支持读写 Unicode,但它是 8-bit-clean 保存 ASCII NUL 字符的一些问题。因此,只要您避免使用像 UTF-16 这样使用 NUL 的编码,您就可以编写函数或类来为您处理编码和解码。推荐使用 UTF-8。

试试下面的代码片段,它为您提供了一个生成器,可以读取带有 unicode 数据的 csv。请注意,此代码直接取自上面链接的文档:

import csv

def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
    # csv.py doesn't do Unicode; encode temporarily as UTF-8:
    csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
                            dialect=dialect, **kwargs)
    for row in csv_reader:
        # decode UTF-8 back to Unicode, cell by cell:
        yield [unicode(cell, 'utf-8') for cell in row]

def utf_8_encoder(unicode_csv_data):
    for line in unicode_csv_data:
        yield line.encode('utf-8')

作为如何使用上述代码的示例,而不是

csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|')

利用

csvReader = unicode_csv_reader(csvfile, delimiter=' ', quotechar='|')

yield是生成器函数的返回等效项。该函数返回一个生成器对象,它是python中的一种可迭代对象。**kwargs表示关键字参数,这是您在编写时实际传递的内容delimiter=' ', quotechar='|'

于 2013-07-09T17:27:14.243 回答
0

问题是,当您的输入中有非 ascii 字符时,您并没有将它们以预期的状态传递给 xlwt。

根据 xlwt 的文档:

一个 unicode 实例按原样编写。使用创建 Workbook 实例时指定的编码(默认值:'ascii')将 str 实例转换为 unicode。

https://secure.simplistix.co.uk/svn/xlwt/trunk/xlwt/doc/xlwt.html?p=4966#xlwt.Worksheet.write-method

也就是说,当您的输入 csv 文件包含使用 utf-8 编码的非 ascii 字符时,阅读器会将其作为编码的 Python 字符串拉入 - 如果您直接查看它,您会看到多个十六进制字节,例如'\xc3\xa1'小写a-急性的。当您将其写入工作表时,它必须对其进行解码。创建工作簿时,您没有指定编码,因此它会尝试使用默认ascii编码来执行此操作。如您所见,这不起作用,因为它们不是 ascii 字节。

您的选择是将 Unicode 字符串传递到工作表,从 csv 阅读器的结果中对其进行解码(或将 csv 阅读器包装在可以解码所有内容的东西中 - 这是同一件事),或者在创建工作簿时设置它的编码。

于 2013-07-09T17:27:28.113 回答
0

尝试使用内置的编解码器库打开文件:

#!/usr/bin/env python2.7
# -*- coding: UTF-8 -*-
import codecs

with codecs.open(sys.argv[1], "rb", encoding="utf-8") as csvfile:
    csvReader = csv.reader(csvfile, delimiter=' ', quotechar='|')
    # snipped the rest of the code
于 2013-07-09T17:27:53.067 回答