【问题标题】:Python 2.7 - Pandas UnicodeEncodeError with data from pyodbcPython 2.7 - 带有来自 pyodbc 的数据的 Pandas UnicodeEncodeError
【发布时间】:2019-11-01 14:33:02
【问题描述】:

我正在尝试使用 pyodbc 从 SQL Server 提取数据并将其加载到数据帧中,然后将其导出到 HTML 文件,但我不断收到以下 Unicode 错误:

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

这是我当前的设置(每个 docs 的编码说明):

cnxn =  pyodbc.connect('DSN=Planning;UID=USER;PWD=PASSWORD;')
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='cp1252', to=unicode)
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='cp1252', to=unicode)
cnxn.setdecoding(pyodbc.SQL_WMETADATA, encoding='cp1252', to=unicode)
cnxn.setencoding(str, encoding='utf-8')
cnxn.setencoding(unicode, encoding='utf-8')
cursor = cnxn.cursor()

with open('Initial Dataset.sql') as f:
    initial_query = f.read()

cursor.execute(initial_query)
columns = [column[0] for column in cursor.description]
initial_data = cursor.fetchall()
i_df = pd.DataFrame.from_records(initial_data, columns=columns)
i_df.to_html('initial.html')

需要注意的一个奇怪但有用的一点是,当我尝试导出 CSV 时:

i_df.to_csv('initial.csv')

我得到同样的错误,但是当我添加时:

i_df.to_csv('initial.csv', encoding='utf-8')

它有效。有人可以帮我理解这个编码问题吗?

旁注:我也尝试过使用sqlalchemy 连接和pandas.read_sql(),但同样的错误仍然存​​在。

【问题讨论】:

  • 该错误意味着您正在尝试将无法以 ASCII 表示的 (Unicode) 字符编码为 ASCII。我只是在猜测,但你的 pandas 返回的数据帧是用 utf-8 编码的。我怀疑 to=unicode 是错误的,但只是在黑暗中拍摄。
  • 我理解错误的含义,我只是不明白为什么会发生。数据帧是utf-8 编码的。 pandas.to_htmldocs 相当少。为什么在生成 HTML 时会尝试转换为 ASCII?
  • 我不确定,但我会检查 pandas.to_html 源代码,看看那里发生了什么(也许编码默认为 ASCII,我不知道)。
  • 在使用 SQL Server 时,您根本不需要任何 setencoding/setdecoding 调用,尤其是不需要编码为 UTF-8,而 SQL Server ODBC 不使用(它使用 UTF- 16,这是 pyodbc 的默认编码)。
  • 来自here:“SQL Server 的最新驱动符合规范,因此无需配置。建议使用 pyodbc 默认值。”

标签: python pandas pyodbc


【解决方案1】:

this question 上的第二个答案似乎是一个可以接受的解决方法,除了 Python 2.x 用户,您必须使用io,所以:

import io

html = df.to_html()
with io.open("mypage.html", "w", encoding="utf-8") as file:
    file.write(html)

它未包含在最新版本中,但看起来pandas 的下一个版本将为to_html() 提供encoding 选项,请参阅docs(第2228 行)。

【讨论】:

  • 是的,没错。编码应该应用于输出文件,而不是 pyodbc 和 SQL Server 之间的通信。
  • 问题最终出在熊猫身上,因为to_html() 似乎强制执行 ASCII 编码。看来他们将在即将发布的版本中解决该问题。
  • "to_html() 似乎强制执行 ASCII 编码" - 不,to_html 更有可能在您只传递一个字符串(文件路径) 对于buf=,Python_2 的默认字符串编码是 ASCII。
  • @GordThompson 好的,但是使用 Python 2 并没有办法告诉函数使用不同的编码,这实际上是一回事,不是吗?
  • “告诉函数”的方法是传递一个buf 参数,它是一个类似StringIO 的对象,而不仅仅是一个(字符串)路径。
猜你喜欢
  • 2020-06-18
  • 2018-05-18
  • 1970-01-01
  • 2019-05-16
  • 2022-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多