如何使用 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 发行版),则应自动使用正确的输出编解码器。
相关:
- Python 2 Unicode howto
- Pragmatic Unicode, or, How do I stop the pain?
- Setting the correct encoding when piping stdout in Python
.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.
我收到一个 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 发行版),则应自动使用正确的输出编解码器。
相关:
- Python 2 Unicode howto
- Pragmatic Unicode, or, How do I stop the pain?
- Setting the correct encoding when piping stdout in Python
.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.