我开始使用蟒蛇试图在sqlite的存储字符串,并得到了消息:
sqlite3.ProgrammingError:除非你使用的是可以解释的8位字节串(如text_factory = STR)一text_factory不得使用8位字节串。 强烈建议您改为只需切换您的应用程序Unicode字符串。
好吧,我切换到Unicode字符串。 然后,我开始收到消息:
sqlite3.OperationalError:无法解码为UTF-8列“tag_artist”文本“西格尔罗斯”
当试图检索数据库的数据。 更多的研究,我开始编码它在UTF8,但随后“西格尔罗斯”开始看起来像“西格尔Rós”
注:我的控制台被设置在“LATIN_1”显示为@约翰梅钦指出。
是什么赋予了? 看完这个 ,恰恰说明了同样的情况,我在,它看来,如果建议是忽略其他建议毕竟使用8位字节串。
我不知道很多关于Unicode和UTF之前,我开始这个过程。 我已经学到了很多在过去的几个小时,但我仍然懵懂是否有正确转换的方式“O”来自拉丁美洲-1为UTF-8,而不是裂伤它。 如果没有,为什么会SQLite的“强烈推荐”我在我的应用程序切换到unicode字符串?
我要更新与总结,一切我已经在过去24小时内学会让别人在我的鞋能有一个简单的(ER)引导的一些示例代码这个问题。 如果我发布的信息以任何方式错误或误导性的请告诉我,我会更新,或者你资深的球员之一可以更新。
答案汇总
首先,我要声明的目标,因为我了解它。 在处理各种编码的目标,如果你正尝试将它们之间的转换,是要了解你的源编码是什么,然后将其转换使用源编码为Unicode,然后将其转换为所需的编码。 Unicode是一种碱和编码是基的子集的映射。 UTF_8有余地unicode的每个字符,而是因为他们不在同一个地方,例如,LATIN_1,在UTF_8编码并发送至LATIN_1控制台不会看你期望的方式的字符串。 在蟒蛇越来越为Unicode并到另一个编码的过程是这样的:
str.decode('source_encoding').encode('desired_encoding')
或者如果str是已经以Unicode
str.encode('desired_encoding')
SQLite的我其实没有想再次对其编码,我想它解码并把它留在Unicode格式。 以下是你可能需要知道的,当你试图使用Unicode和编码在Python工作四件事情。
- 你要使用的字符串编码和编码要得到它。
- 该系统的编码。
- 控制台编码。
- 源文件的编码
阐述:
(1)当读取来自源的字符串,它必须有一些编码,像LATIN_1或UTF_8。 就我而言,我越来越从文件名字符串,所以很遗憾,我可以得到任何类别的编码。 Windows XP使用UCS-2(Unicode系统)作为其原生字符串类型,这似乎是骗我的。 幸运的是,在大多数文件名中的字符不会被由一个以上的源编码类型的,我认为所有我的要么完全LATIN_1,完全UTF_8,或只是普通的ASCII(这是两者的一个子集那些)。 所以,我只是阅读并解码他们,如果他们仍然在LATIN_1或UTF_8。 这是可能的,虽然,你可以在Windows上的文件名混合在一起LATIN_1和UTF_8和任何其他字符。 有时,这些字符可以显示为框,其他时间他们只是看缺胳膊少腿,其他时候,他们看起来是正确的(重音字符和诸如此类的东西)。 继续。
(2)Python有时设置蟒启动时和运行时期间不能改变默认的系统编码。 见这里了解详情。 肮脏的总结...那么这里是我添加的文件:
\# sitecustomize.py
\# this file can be anywhere in your Python path,
\# but it usually goes in ${pythondir}/lib/site-packages/
import sys
sys.setdefaultencoding('utf_8')
该系统的编码是当您使用的Unicode(“STR”)功能,无需任何其他的编码参数被使用的一个。 如果说另一种方式,蟒蛇试图基于默认的系统编码“STR”解码为Unicode。
(3)如果你使用IDLE或命令行Python,我认为你的控制台将根据默认的系统编码显示。 我使用的PyDev使用Eclipse出于某种原因,所以我不得不去到我的项目设置,编辑我的测试脚本的启动配置属性,转到Common选项卡,并从Latin-1的改变控制台为UTF-8,这样我可以直观地确认我在做什么是工作。
(4)如果你想有一些测试字符串,如
test_str = "ó"
在你的源代码,那么你将要告诉您使用的是该文件是什么样的编码的蟒蛇。 (供参考:当我键入了错误的编码,我不得不按Ctrl-Z,因为我的文件变得不可读。)这是很容易把一条线,像这样在你的源代码文件的顶部来完成:
# -*- coding: utf_8 -*-
如果你没有这个信息,蟒蛇尝试解析您的代码作为默认的ASCII,所以:
SyntaxError: Non-ASCII character '\xf3' in file _redacted_ on line 81, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
一旦你的程序正常工作,或者,如果你不使用Python的控制台或任何其他控制台来看看输出,那么你可能会真正关心的#1就行了。 除非你需要看看输出和/或您使用的是内置的unicode()函数(不带任何编码参数),而不是string.decode()函数,系统默认和控制台的编码并不是那么重要。 我写了一个演示功能,我会贴到这个巨大的混乱,我希望正确表明了我的列表中的项目的底部。 下面是一些输出的时候我通过演示功能运行字符“O”,表示各种方法如何反应,从而将字符作为输入。 我的系统编码和控制台输出都被设置为UTF_8就该运行而言:
'�' = original char <type 'str'> repr(char)='\xf3'
'?' = unicode(char) ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data
'ó' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8') ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data
现在,我将改变系统和控制台编码LATIN_1,我得到这个输出相同的输入:
'ó' = original char <type 'str'> repr(char)='\xf3'
'ó' = unicode(char) <type 'unicode'> repr(unicode(char))=u'\xf3'
'ó' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8') ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data
请注意,“原始”字符正确显示现在内置的unicode()函数的工作。
现在,我改变我的控制台输出回UTF_8。
'�' = original char <type 'str'> repr(char)='\xf3'
'�' = unicode(char) <type 'unicode'> repr(unicode(char))=u'\xf3'
'�' = char.decode('latin_1') <type 'unicode'> repr(char.decode('latin_1'))=u'\xf3'
'?' = char.decode('utf_8') ERROR: 'utf8' codec can't decode byte 0xf3 in position 0: unexpected end of data
这里的一切仍然有效,与去年相同的时间,但控制台无法正确显示输出。 等了以下功能也显示更多的信息,这并希望能帮助别人揣摩出在他们的理解的差距。 我知道,所有这些信息在其他的地方,并有更彻底的处理,但我希望这将是有人试图让Python和/或sqlite的编码良好的开球点。 思想是伟大的,但有时的源代码可以节省您的试图找出哪些功能做什么或两天。
免责声明:我不是专家编码,我把这个在一起,帮助我自己的理解。 我一直建立在它的时候,我应该有可能开始传递函数作为参数,以避免这么多冗余的代码,所以如果我可以,我会让它更加简洁。 此外,UTF_8和LATIN_1绝不是唯一的编码方案,他们只是两个我用,因为我觉得他们处理一切,我需要打转转。 你自己的编码方案添加到演示功能和测试自己的输入。
还有一两件事:有明显疯了应用开发商真难在Windows中。
#!/usr/bin/env python
# -*- coding: utf_8 -*-
import os
import sys
def encodingDemo(str):
validStrings = ()
try:
print "str =",str,"{0} repr(str) = {1}".format(type(str), repr(str))
validStrings += ((str,""),)
except UnicodeEncodeError as ude:
print "Couldn't print the str itself because the console is set to an encoding that doesn't understand some character in the string. See error:\n\t",
print ude
try:
x = unicode(str)
print "unicode(str) = ",x
validStrings+= ((x, " decoded into unicode by the default system encoding"),)
except UnicodeDecodeError as ude:
print "ERROR. unicode(str) couldn't decode the string because the system encoding is set to an encoding that doesn't understand some character in the string."
print "\tThe system encoding is set to {0}. See error:\n\t".format(sys.getdefaultencoding()),
print ude
except UnicodeEncodeError as uee:
print "ERROR. Couldn't print the unicode(str) because the console is set to an encoding that doesn't understand some character in the string. See error:\n\t",
print uee
try:
x = str.decode('latin_1')
print "str.decode('latin_1') =",x
validStrings+= ((x, " decoded with latin_1 into unicode"),)
try:
print "str.decode('latin_1').encode('utf_8') =",str.decode('latin_1').encode('utf_8')
validStrings+= ((x, " decoded with latin_1 into unicode and encoded into utf_8"),)
except UnicodeDecodeError as ude:
print "The string was decoded into unicode using the latin_1 encoding, but couldn't be encoded into utf_8. See error:\n\t",
print ude
except UnicodeDecodeError as ude:
print "Something didn't work, probably because the string wasn't latin_1 encoded. See error:\n\t",
print ude
except UnicodeEncodeError as uee:
print "ERROR. Couldn't print the str.decode('latin_1') because the console is set to an encoding that doesn't understand some character in the string. See error:\n\t",
print uee
try:
x = str.decode('utf_8')
print "str.decode('utf_8') =",x
validStrings+= ((x, " decoded with utf_8 into unicode"),)
try:
print "str.decode('utf_8').encode('latin_1') =",str.decode('utf_8').encode('latin_1')
except UnicodeDecodeError as ude:
print "str.decode('utf_8').encode('latin_1') didn't work. The string was decoded into unicode using the utf_8 encoding, but couldn't be encoded into latin_1. See error:\n\t",
validStrings+= ((x, " decoded with utf_8 into unicode and encoded into latin_1"),)
print ude
except UnicodeDecodeError as ude:
print "str.decode('utf_8') didn't work, probably because the string wasn't utf_8 encoded. See error:\n\t",
print ude
except UnicodeEncodeError as uee:
print "ERROR. Couldn't print the str.decode('utf_8') because the console is set to an encoding that doesn't understand some character in the string. See error:\n\t",uee
print
print "Printing information about each character in the original string."
for char in str:
try:
print "\t'" + char + "' = original char {0} repr(char)={1}".format(type(char), repr(char))
except UnicodeDecodeError as ude:
print "\t'?' = original char {0} repr(char)={1} ERROR PRINTING: {2}".format(type(char), repr(char), ude)
except UnicodeEncodeError as uee:
print "\t'?' = original char {0} repr(char)={1} ERROR PRINTING: {2}".format(type(char), repr(char), uee)
print uee
try:
x = unicode(char)
print "\t'" + x + "' = unicode(char) {1} repr(unicode(char))={2}".format(x, type(x), repr(x))
except UnicodeDecodeError as ude:
print "\t'?' = unicode(char) ERROR: {0}".format(ude)
except UnicodeEncodeError as uee:
print "\t'?' = unicode(char) {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)
try:
x = char.decode('latin_1')
print "\t'" + x + "' = char.decode('latin_1') {1} repr(char.decode('latin_1'))={2}".format(x, type(x), repr(x))
except UnicodeDecodeError as ude:
print "\t'?' = char.decode('latin_1') ERROR: {0}".format(ude)
except UnicodeEncodeError as uee:
print "\t'?' = char.decode('latin_1') {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)
try:
x = char.decode('utf_8')
print "\t'" + x + "' = char.decode('utf_8') {1} repr(char.decode('utf_8'))={2}".format(x, type(x), repr(x))
except UnicodeDecodeError as ude:
print "\t'?' = char.decode('utf_8') ERROR: {0}".format(ude)
except UnicodeEncodeError as uee:
print "\t'?' = char.decode('utf_8') {0} repr(char)={1} ERROR PRINTING: {2}".format(type(x), repr(x), uee)
print
x = 'ó'
encodingDemo(x)
许多感谢您的答案下方,尤其是@约翰梅钦回答得如此彻底。