如何使用 Python 读取 excel Unicode 字符

How to read excel Unicode characters using Python

我收到一个 Excel 文件,我无法影响其内容。它包含一些 Unicode 字符,例如“á”或“é”。

我的代码没有改变,但是我从 Eclipse Juno 迁移到 LiClipse 一起迁移到不同的 python 包(从 2.5 到 2.6)。原则上,我使用的特定包在 win32com 包上有一个工作版本。

当我读取 Excel 文件时,我的代码在使用 str() 提取和转换为字符串时崩溃。控制台输出如下:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 89: ordinal not in range(128)

为了更具体,我执行以下操作:

阅读Excel:

  xlApp = Dispatch("Excel.Application")

  excel = xlApp.Workbooks.Open(excel_location)

在内部循环中,我提取了单元格的值:

cell_value = self.excel.ActiveSheet.Cells(excel_line + 1, excel_column + 1)

最后,如果我尝试将 cell_value 转换为 str,崩溃:

print str(cell_value)

如果我转到 Excel 并删除非 ASCII 字符,一切都会顺利进行。我试过这个encode proposal。我用谷歌搜索过的任何其他解决方案都建议以特定格式保存文件,但我做不到。

让我感到困惑的是,代码之前使用相同的输入 Excel 但这次对 LiClipse 和 2.6 Python 的更改杀死了一切。

知道我该如何进步吗?

这是在 Python 2.x 中使用 UTF-8 编码的 Unicode 数据时的常见问题。在 2.4 和 2.7 之间的几个地方对此的处理发生了变化,因此突然出现错误也就不足为奇了。

错误的来源是 print:在 Python 2.x 中,print 没有尝试假设您的终端支持什么编码。它只是播放保存并假设 ascii 是唯一受支持的字符集(这意味着 0 到 127 之间的字符都可以,其他一切都会出错)。

现在将 COMObject 转换为字符串。就 Python 2.x 而言,str 只是一堆字节(值 0 到 255)。它没有编码。

将两者结合起来会带来麻烦。当 Python 打印时,它尝试验证输入(字符串)并突然发现 UTF-8 编码字符(UTF-8 添加这些奇怪的 \xe1 标记,告诉解码器下一个字节是特殊的某种方式;check Wikipedia for the gory details).

那时 ascii 编码器会说:抱歉,无法帮助您。

这意味着你可以使用这个值,比较它等等,但你不能 print 它。打印问题的简单解决方法是:

s = str(cell_value) # Convert COM -> UTF-8 encoded string
print repr(s) # repr() converts anything to ascii

如果你的终端支持UTF-8,那么你需要告诉Python:

import sys
import codecs

sys.stdout = codecs.getwriter('utf8')(sys.stdout)

您还应该看看 sys.stdout.encoding,它告诉 Python 当前认为输出编码 is/should 是什么。当 Python 2 正确配置时(如现代 Linux 发行版),则应自动使用正确的输出编解码器。

相关:

.Cells(row,col) returns 一个 Range 对象。您可能需要单元格中的文本:

cell = xl.ActiveSheet.Cells(1,2).Text

cell = xl.ActiveSheet.Range('B1').Text

结果值将是一个 Unicode 字符串。要转换为可以写入文件的字节,请使用 .encode(encoding),例如:

bytes = cell.encode('utf8')

以下示例使用以下电子表格:

import win32com.client
xl = win32com.client.gencache.EnsureDispatch('Excel.Application')
xl.Workbooks.Open(r'book1.xlsx')
cell = xl.ActiveSheet.Cells(1,2)
cell_value = cell.Text
print repr(cell)
print repr(cell_value)
print cell_value

输出(注意,只有console/IDE支持字符才会打印中文):

<win32com.gen_py.Microsoft Excel 14.0 Object Library.Range instance at 0x129909424>
u'\u4e2d\u56fd\u4eba'
中国人

What is described here is a hack, you should not use as a long term solution. Looking at the comments it could crush the terminal.

在@Huan-YuTseng 提供的建议下,我终于找到了一个解决方案,可能其他人提供的解决方案可能在其他上下文中有效,但在这个上下文中无效。

所以,发生的事情是我从 Eclipse Juno 版本(因为 Pydev 由于 Java 需要升级而停止工作,我无法在这台计算机上完成)迁移到 LiClipse 直接包(我没有升级下载的 Eclipse 版本)。

默认情况下,在我的 LiClipse 版本 (1.4.0.201502042042) 中,控制台输出不是默认的 utf-8。所以我需要更改 LiClipse 或使用我的代码的输出。幸运的是,还有另一个与类似问题相关的问题对我有所帮助。您可以看到更多详细信息 here,但本质上您需要做的是在代码的开头包含以下代码:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

一切正常。在@AarongDigulla 的回答中,解决方案就在那里,但实际上是最后一个解决方案。

但是,我需要说 LiClipse 在 sys.setdefaultencoding 语句中给我一个错误,在执行过程中不会产生任何问题...不知道发生了什么。这阻止了我之前测试这个解决方案。可能是 LiClipse 出了问题(让我执行有错误的代码!)

使用 'utf-8 BOM',在 python 中用作 utf_8_sig Unicode 字符,同时避免在 Excel 中出现不相关的结果sheet.