Python与MySql unicode问题

问题描述:

我需要从我的python脚本调用MySQL存储过程。作为参数之一,我传递了一个unicode字符串(俄语),但我得到一个错误;Python与MySql unicode问题

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 0-1: ordinal not in range(256)

我的脚本:

self.db=MySQLdb.connect("localhost", "usr", "pass", "dbName") 
    self.cursor=self.db.cursor() 
    args=("какой-то текст") #this is string in russian 
    self.cursor.callproc('pr_MyProc', args) 
    self.cursor.execute('SELECT @_pr_MyProc_2') #getting result from sp 
    result=self.cursor.fetchone() 
    self.db.commit() 

我读过设置charset='utf8' shuld解决此问题,但是当我使用的字符串:

self.db=MySQLdb.connect("localhost", "usr", "pass", "dbName", charset='utf8') 

这给了我另一个错误;

UnicodeEncodeError: 'utf-8' codec can't encode character '\udcd1' in position 20: surrogates not allowed

另外我试图设置参数use_unicode=True,这是行不通的。

+0

它的工作原理(u“какой-тотекст”)'? –

+0

@DanielRoseman不,我也试过了。 – Gleb

+0

是这个蟒蛇2或3? –

更多的事情来检查: http://mysql.rjweb.org/doc.php/charcoll#python

可能的项目:

  • 启动代码文件,# -*- coding: utf-8 -*- - (在代码中的文字)
  • 字面应该是U '......'

你可以提取HEX? какой-то текст应该是这个在utf8中:D0BA D0B0 D0BA D0BE D0B9 2D D182 D0BE D182 20 D0B5 D0BA D181 D182

+2

据我所知“# - * - coding:utf-8 - * - ”设置文件的编码,而不是字符串。所以它没有帮助。 – Gleb

+0

它在你的情况下受伤了吗? –

MySQLdb模块与python 3不兼容。这可能是你遇到问题的原因。我建议使用不同的连接器,如PyMySQLmysqlclient

相关:23376103

+1

我正在使用mysqlclinet – Gleb

这里有一些想法。也许不是一个回应。我一直在玩蟒蛇/ MySQL的/ UTF-8/Unicode的过去,这是事情我记得:

看着Saltstack mysql的模块的评论:

https://github.com/saltstack/salt/blob/develop/salt/modules/mysql.py#L314-L322

# MySQLdb states that this is required for charset usage 
# but in fact it's more than it's internally activated 
# when charset is used, activating use_unicode here would 
# retrieve utf8 strings as unicode() objects in salt 
# and we do not want that. 
#_connarg('connection_use_unicode', 'use_unicode') 
connargs['use_unicode'] = False 
_connarg('connection_charset', 'charset') 

我们请参阅以避免更改结果字符串use_unicode设置为False,而charset(可能是utf-8)被设置为参数。 use_unicode更像是一个'请求',以响应为unicode字符串。

您可以在测试中检查实际使用情况,这里是: https://github.com/saltstack/salt/blob/develop/tests/integration/modules/test_mysql.py#L311-L361,数据库名为'标准语'。

现在关于消息UnicodeEncodeError:'utf-8'编解码器无法编码字符'\ udcd1'**。您正在使用** unicode,但您告诉模块它是utf-8。它不是utf-8,直到你在utf-8中编码你的unicode字符串。

也许你应该尝试:

args=(u"какой-то текст".encode('utf-8')) 

至少在python3这是必需的,因为你的 “какой-тотекст” 是不是UTF-8在默认情况下。

+0

现在链接已损坏:我找到了新的链接:https://github.com/saltstack/salt/blob/develop/tests/integration/modules/test_mysql.py#L311-L361(note file_name更改) – bdeo

+0

谢谢,链接已更新 – regilero

什么是数据库的字符集?
使用:

show variables like "characetr%"; 

或看到你的数据库的字符集

也许你可以重新载入你的sysutf-8,并尝试将字符串解码成utf-8如下:

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

... 

stringUtf8 = u''.join(string_original).decode('utf-8') 

我看到这里有两个问题。

  1. 你有unicode,但你尝试通过设置参数“charset”来定义它为utf-8。您应该先将Unicode编码为utf-8或其他编码系统。

  2. 如果它不起作用,请尝试使用init_command ='SET NAMES UTF8'参数。

所以它看起来像:

conn = MySQLdb.connect(charset='utf8', init_command='SET NAMES UTF8') 

你也可以这样试试:

cursor = db.cursor() 

cursor.execute("SET NAMES UTF8;") 

我有一个类似的问题,最近,但在PostgreSQL。在尝试了大量来自SO/Internet的建议后,我意识到问题出在我的数据库上。我不得不放弃我的数据库并重新安装Postgres,因为出于某种原因,它不允许我更改数据库的默认排序规则。我很匆忙,所以找不到更好的解决方案,但会推荐相同的,因为我只是在部署环境中启动我的应用程序。 一切顺利。

我遇到了类似的问题,这是由于数据库中无效的utf-8数据造成的;似乎MySQL不关心这个,但是Python做,因为这是继UTF-8的规格,它说that

  • 代理对中无法使用UTF-8
  • 不成对的代理人都没有允许在utf-8中

如果你想“让它工作”,你将不得不截获MySQL数据包并使用你自己的转换器来执行临时替换。

这里的“处理”含代理人无效数据的一种方法:

def borked_utf8_decode(data): 
    """ 
    Work around input with unpaired surrogates or surrogate pairs, 
    replacing by XML char refs: look for "&#\d+;" after. 
    """ 
    return data.decode("utf-8", "surrogatepass") \ 
    .encode("utf-8", "xmlcharrefreplace") \ 
    .decode("utf-8") 

注意处理的正确方法是上下文相关,但也有一些共同的替代方案中,像this one

而且这里有一个方法插入到pymysql这个的(另一种方式是猴子补丁场处理,例如见https://github.com/PyMySQL/PyMySQL/issues/631):`ARGS =:

如果你的unicode字符串发送
import pymysql.converters 

# use this in your connection 
pymysql_use_unicode = False 
conversions = pymysql.converters.conversions 
conversions[pymysql.converters.FIELD_TYPE.STRING] = borked_utf8_decode 
conversions[pymysql.converters.FIELD_TYPE.VAR_STRING] = borked_utf8_decode 
conversions[pymysql.converters.FIELD_TYPE.VARCHAR] = borked_utf8_decode