Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7.1、编解码器和MySQLdb;为什么不需要设置文件编码_Python_Unicode_Python 2.7_Mysql Python_Codec - Fatal编程技术网

Python 2.7.1、编解码器和MySQLdb;为什么不需要设置文件编码

Python 2.7.1、编解码器和MySQLdb;为什么不需要设置文件编码,python,unicode,python-2.7,mysql-python,codec,Python,Unicode,Python 2.7,Mysql Python,Codec,我有一个小型Python程序,它从文件中读入SQL语句并在MySQL数据库上运行它们。文件以UTF-8编码,数据库也使用UTF-8 如果我没有设置数据库编码,我会得到一个通常的错误,每个人都会问“latin-1”编解码器不能编码字符…”。因此,我使用 con.set_character_set('utf8') fh = codecs.open(fname,'r','utf8') 现在它可以工作了,但是当我不设置文件编码(或者只使用内置的open)时,它也可以工作,只是在数据库中。我所说的“工作

我有一个小型Python程序,它从文件中读入SQL语句并在MySQL数据库上运行它们。文件以UTF-8编码,数据库也使用UTF-8

如果我没有设置数据库编码,我会得到一个通常的错误,每个人都会问“latin-1”编解码器不能编码字符…”。因此,我使用

con.set_character_set('utf8')
fh = codecs.open(fname,'r','utf8')
现在它可以工作了,但是当我不设置文件编码(或者只使用内置的open)时,它也可以工作,只是在数据库中。我所说的“工作”是指结果数据库记录在假定为UTF-8的WordPress中正确显示

如果我想要魔法,我会用Ruby编写代码。Python在这种情况下做了什么?为什么不必告诉它文件编码

不用说,我在这方面做了很多搜索,我的GoogleFoo通常都很不错。在这里和博客上都有大量的帖子讨论了为什么有必要设置编码以及如何设置编码,但我还没有找到任何关于为什么它有时会起作用的帖子

编辑: 我使用一个包含“谢谢”的文件对此进行了一个简单的测试

file
  E2 80 9C 54 68 61 6E 6B 20 79 6F 75 2E E2 80 9D
codecs utf8
  201C 54 68 61 6E 6B 20 79 6F 75 2E 201D
试图用编解码器读取。open(myfile,'r','ascii')返回“UnicodeDecodeError:'ascii'编解码器无法解码字节0xe2”

从文件读取时产生了一个字节字符串,因此在插入数据库时似乎发生了奇迹

当您使用

fh = codecs.open(fname,'r','utf8')
fh.read()
返回一个unicode。如果使用此unicode并使用数据库驱动程序(如mysql python)将数据插入数据库,则驱动程序负责将unicode转换为字节。驱动程序正在使用由设置的编码

con.set_character_set('utf8')
如果你使用

fh = open(fname, 'r')
然后
fh.read()
返回一个字节字符串。无论发生在
fname
中的字节是什么,您都将任由其摆布。幸运的是,根据您的帖子,该文件是用UTF-8编码的。由于数据已经是一个字节字符串,因此驱动程序不执行任何编码,只是将字节字符串原样传递给数据库

无论哪种方式,都会将相同的UTF-8编码字节字符串插入数据库


让我们看一下定义以下内容的源代码:

请特别注意,如果未设置
编码
,会发生什么情况:

file = __builtin__.open(filename, mode, buffering)
if encoding is None:
     return file
因此,当未设置编码时,
codecs.open
与内置的
open
基本相同。内置的
open
返回一个file对象,其
read
方法返回一个str对象。它根本不解码

相反,当指定编码时,
codecs.open
返回
StreamReaderWriter
,其中
srw.encoding
设置为
encoding
。现在,当调用
StreamReaderWriter
read
方法时,通常会返回一个unicode对象。首先,必须使用指定的编码对str对象进行解码

在您的示例中,
str
对象是

In [19]: content
Out[19]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
如果将编码指定为
'ascii'
,则
StreamReaderWriter
将尝试使用
'ascii'
编码对
内容进行解码:

In [20]: content.decode('ascii')

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
这并不奇怪,因为
ascii
编码只能对0-127范围内的字节进行解码,而
'\xe2'
(内容
中的第一个字节)的序号值超出了该范围


对于具体性:当您不指定编码时

In [13]: with codecs.open(filename, 'r') as f:
   ....:     content = f.read() 

In [14]: content
Out[14]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
In [22]: with codecs.open(filename, 'r', encoding = 'utf-8') as f:
   ....:     content = f.read()


In [23]: content
Out[23]: u'\u201cThank you.\u201d'
In [25]: with codecs.open(filename, 'r', 'ascii') as f:
   ....:     content = f.read()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
content
是一个
str

指定有效编码时

In [13]: with codecs.open(filename, 'r') as f:
   ....:     content = f.read() 

In [14]: content
Out[14]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
In [22]: with codecs.open(filename, 'r', encoding = 'utf-8') as f:
   ....:     content = f.read()


In [23]: content
Out[23]: u'\u201cThank you.\u201d'
In [25]: with codecs.open(filename, 'r', 'ascii') as f:
   ....:     content = f.read()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
content
是一种
unicode

指定无效编码时

In [13]: with codecs.open(filename, 'r') as f:
   ....:     content = f.read() 

In [14]: content
Out[14]: '\xe2\x80\x9cThank you.\xe2\x80\x9d'
In [22]: with codecs.open(filename, 'r', encoding = 'utf-8') as f:
   ....:     content = f.read()


In [23]: content
Out[23]: u'\u201cThank you.\u201d'
In [25]: with codecs.open(filename, 'r', 'ascii') as f:
   ....:     content = f.read()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)
在Python的第4段中,您得到了一个
UnicodeDecodeError

,它是用than编写的,描述了
codecs.open(filename,mode,[encoding])
函数,您正在使用:

encoding
是提供要使用的编码的字符串;如果保留为None,则返回一个接受8位字符串的常规Python文件对象

此外,在本书中,据说

file.encoding
)也可以是无,在这种情况下,文件使用系统默认编码转换Unicode字符串


调用不带编码参数的
codecs.open()
,返回的文件对象的编码属性为
None
(已测试),因此使用Unicode的系统默认值,在您的情况下,该值必须是UTF-8。这就解释了为什么它在不显式的情况下工作得如此灵活。

除了将文件提供给MySQL之外,您还对文件的内容做了什么吗?Python可以在UTF8中读取,使用常规的old-open就可以了。根据我的经验,当你试图把它写出来时,通常会出现“latin-1 codec can not encode”错误。我把结果数据库交给WordPress,它假设是UTF8。当它工作正常时,文本显示正常,当它不工作时,文本显示许多奇怪的字符。“用常规的旧版本阅读它很好”,这让我感到困惑,因为我认为默认编码是ISO 8859-1。@anov,谢谢,我已经在问题中添加了“works”的定义。我如何确定系统默认编码?使用open是否等同于使用codecs.open而不指定编码?当我使用内置的open()时,这是如何工作的?我已经编辑了问题以添加此内容。是的,使用
open()
返回一个编码属性为
None
文件
对象,该属性与
编解码器相同。在不带编码参数的情况下打开
。通过执行
sys.getdefaultencoding()
,可以找到系统默认编码。要更改它,请参见“谢谢”,我使用的是Mac,sys.getdefaultencoding()返回ascii。所以不清楚它为什么有效,我明白了。您能否从代码中提供更多信息,例如将
fh
的内容发送到数据库的行