【问题标题】:pyodbc doesn't correctly deal with unicode datapyodbc 无法正确处理 unicode 数据
【发布时间】:2017-08-04 11:26:43
【问题描述】:

我确实成功地将 MySQL 数据库与 pyodbc 连接起来,它与 ascii 编码的数据配合得很好,但是当我打印用 unicode(utf8) 编码的数据时,它引发了错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-8: ordinal not in range(128)

所以我检查了行中的字符串:

>>>row[3]
'\xe7\xae\xa1\xe7\x90\u2020\xe5\u2018\u02dc'

我找到instructions about unicode in pyodbc github wiki

这些数据库倾向于使用单一编码并且不区分 在“SQL_CHAR”和“SQL_WCHAR”之间。因此,您必须配置它们 将 Unicode 数据编码为 UTF-8 并对两种 C 缓冲区类型进行解码 使用 UTF-8。

# Python 3.x
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
cnxn.setencoding(encoding='utf-8')

如果您使用的是 MySQL,您可以将字符集添加到 连接字符串,但我不确定这是否有必要。

# MySQL
cstring = 'DSN=mydsn;CharSet=utf8'
cnxn = pyodbc.connect(cstring)

我按照上面的方法做了,但没有什么不同。 流动是我的代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pyodbc
import configparser
class ServerDBDAO():
    def __init__(self):
        ''' Establish connection to SQL'''
        # Read config
        self.cf = configparser.ConfigParser()
        self.cf.read("./Config/server.ini")
        driver = self.cf.get('Database', 'Driver')
        server = self.cf.get('Database', 'Server')
        database = self.cf.get('Database', 'Database')
        uid = self.cf.get('Database', 'UID')
        pwd = self.cf.get('Database', 'PWD')

        # Connect database
        connString = 'DRIVER=%s;SERVER=%s;DATABASE=%s;UID=%s;PWD=%s;CharSet=utf8'%(driver, server, database, uid, pwd)
        '''Successfully connected database with this
        self.conn = pyodbc.connect('DRIVER=/usr/lib/x86_64-linux-gnu/odbc/libmyodbc.so;SERVER=localhost;DATABASE=xxx;UID=root;PWD=xxxxxx'))
        '''
        self.conn = pyodbc.connect(connString,unicode_results=True)
        self.conn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
        self.conn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
        self.conn.setencoding(encoding='utf-8')
        self.cursor = self.conn.cursor()

    def __del__(self):
        self.conn.commit()
        self.conn.close()

测试代码:

from ServerDBDAO import ServerDBDAO
dbdao = ServerDBDAO()
row_employee = cursor.execute('select id, name, email from Employee;').fetchone()
print(row_employee.name)

【问题讨论】:

  • 您尝试使用哪个版本的 MySQL 连接器/ODBC?你是怎么安装的?您的问题提到了libmyodbc.so,但当前版本的 MySQL ODBC 驱动程序实际上有两种形式:libmyodbc5a.so 用于“ANSI”,libmyodbc5w.so 用于 Unicode。你确定你使用的版本支持Unicode吗?
  • 不要在您的代码中进行任何编码/解码。就让它全部是 UTF-8。
  • @GordThompson 我只是用 'apt-get install libmyodbc' 安装了 odbc,它只提供了这个 libmyodbc.so 文件。我将尝试 libmyodbc5w.so 并看看它是如何工作的。非常感谢您的帮助!
  • @RickJames 我一开始没有使用编码和解码的东西,它没有用,所以我根据 pyodbc wiki 添加了代码,它没有用以太方式工作。还是谢谢你的回复。
  • @GordThompson 我从 mysql 官方网站link 安装了 MySQL Connector/ODBC 5.3。尝试了libmyodbc5w.so,又遇到了连接link的错误,用软链接解决了,但是还是像以前一样引发了UnicodeEncodeError。

标签: python mysql encoding utf-8 pyodbc


【解决方案1】:

我遇到了同样的问题。除了使用这些:

cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
cnxn.setencoding(encoding='utf-8')

添加这个解决了我的问题:

cnxn.setdecoding(pyodbc.SQL_WMETADATA, encoding='utf-32le')

【讨论】:

  • 这很有趣...我听说 MySQL 'utf-8' 编码不是真正的 utf-8 标准编码,它是 MySQL 发明的编码。相反,MySQL 中的 'utf8mb4' 是真正的 utf-8。不确定这是否是根本原因,我早就放弃了环境,可能无法重现它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-21
  • 2012-07-18
相关资源
最近更新 更多