String Python';shell字符串的处理
我仍然不完全理解python的unicode和str类型是如何工作的。注意:我使用的是Python2,据我所知,Python3对同一问题有完全不同的方法 我所知道的:String Python';shell字符串的处理,string,unicode,encoding,utf-8,python-2.x,String,Unicode,Encoding,Utf 8,Python 2.x,我仍然不完全理解python的unicode和str类型是如何工作的。注意:我使用的是Python2,据我所知,Python3对同一问题有完全不同的方法 我所知道的: str是一种古老的野兽,它保存的字符串编码方式是历史迫使我们使用的太多编码方式之一 unicode是一种更标准化的表示字符串的方法,它使用一个包含所有可能字符、表情符号、狗屎的小图片等的巨大表格 decode函数将字符串转换为unicode,encode则相反 如果我在python的shell中简单地说: >>>
str
是一种古老的野兽,它保存的字符串编码方式是历史迫使我们使用的太多编码方式之一
unicode
是一种更标准化的表示字符串的方法,它使用一个包含所有可能字符、表情符号、狗屎的小图片等的巨大表格
decode
函数将字符串转换为unicode,encode
则相反
如果我在python的shell中简单地说:
>>> my_string = "some string"
然后my_string
是一个str
变量,用ascii
编码(由于ascii是utf-8的一个子集,所以它也用utf-8
编码)
因此,例如,我可以通过以下语句之一将其转换为unicode
变量:
>>> my_string.decode('ascii')
u'some string'
>>> my_string.decode('utf-8')
u'some string'
我所不知道的:
Python如何处理在shell中传递的非ascii字符串,知道了这一点,保存单词“kožušček”的正确方法是什么
例如,我可以说
>>> s1 = 'kožušček'
在这种情况下,s1
成为我无法转换为unicode
的str
实例:
>>> s1='kožušček'
>>> s1
'ko\x9eu\x9a\xe8ek'
>>> print s1
kožušček
>>> s1.decode('ascii')
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
s1.decode('ascii')
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9e in position 2: ordinal not in range(128)
但是,当我打印s2时,我得到了
>>> print s2
kouèek
这意味着Python丢失了一整封信。有人能给我解释一下吗?
str
对象包含字节。这些字节代表的是什么,Python并没有规定。如果生成了与ASCII兼容的字节,则可以将它们解码为ASCII。如果它们包含表示UTF-8数据的字节,则可以对其进行解码。如果它们包含表示图像的字节,则可以解码该信息并在某处显示图像。当您在str
对象上使用repr()
时,Python将保留任何ASCII可打印的字节,其余字节将转换为转义序列;这使得即使在仅ASCII的环境中调试此类信息也很实用
运行交互式解释器的终端或控制台将字节写入Python键入时读取的stdin
流。这些字节根据终端或控制台的配置进行编码
在您的情况下,控制台很可能将您键入的输入编码到Windows代码页。您需要找出确切的代码页,并使用该编解码器对字节进行解码。代码页1252似乎适合:
>>> print 'ko\x9eu\x9a\xe8ek'.decode('cp1252')
kožušèek
当您打印这些相同的字节时,您的控制台正在读取这些字节,并在已配置的相同编解码器中对其进行解释
Python可以告诉您它认为您的控制台设置了什么编解码器;它尝试为Unicode文本检测此信息,其中必须为您解码输入。它使用来确定这一点,并且sys.stdin
和sys.stdout
对象具有encoding
属性;矿山设置为UTF-8:
>>> import sys
>>> sys.stdin.encoding
'UTF-8'
>>> import locale
>>> locale.getpreferredencoding()
'UTF-8'
>>> 'kožušèek'
'ko\xc5\xbeu\xc5\xa1\xc3\xa8ek'
>>> u'kožušèek'
u'ko\u017eu\u0161\xe8ek'
>>> print u'kožušèek'
kožušèek
因为我的终端已经配置为UTF-8,而Python已经检测到了这一点,所以使用Unicode文本u'…'
works。数据由Python自动解码
我不知道为什么你的安慰信丢失了一整封信;我必须访问您的控制台并进行更多的实验,查看打印repr(s2)
的输出,并测试0x00和0xFF之间的所有字节,看看这是在控制台的输入端还是输出端
我建议您仔细阅读Python和Unicode:
- 内德·巴奇尔德
- 乔尔斯波尔斯基
sys.getdefaultencoding()
编码;它只是在转换时使用的默认值,而不告诉它编码,如:
>>> sys.getdefaultencoding()
'ascii'
>>> unicode(s1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 2: ordinal not in range(128)
使用这个我们可以解码字符串:
>>> u1=s1.decode(locale.getdefaultlocale()[1])
>>> u1
u'ko\u017eu\u0161\u010dek'
>>> print u1
kožušček
有可能没有设置区域设置,就像'C'
区域设置一样。这可能会导致报告的编码为None
,即使默认值为“ascii”
。通常情况下,这是setlocale
的工作,它将自动调用getpreferredencoding
。我建议在程序启动时调用它一次,并保存返回的值以供以后使用。用于文件名的编码也可能是另一种情况,在sys.getfilesystemencoding()中报告
Python内部默认编码由设置,其中包含:
def setencoding():
"""Set the string encoding used by the Unicode implementation. The
default is 'ascii', but if you're willing to experiment, you can
change this."""
encoding = "ascii" # Default value set by _PyUnicode_Init()
if 0:
# Enable to support locale aware default string encodings.
import locale
loc = locale.getdefaultlocale()
if loc[1]:
encoding = loc[1]
if 0:
# Enable to switch off string to Unicode coercion and implicit
# Unicode to string conversion.
encoding = "undefined"
if encoding != "ascii":
# On Non-Unicode builds this will raise an AttributeError...
sys.setdefaultencoding(encoding) # Needs Python Unicode build !
因此,如果希望在每次运行Python时都默认设置它,可以将第一个
if 0
更改为if 1
你是说交互式口译员。它从stdin
流中读取,在这里进行编码的是您的控制台或终端。请您指定您是在谈论python2还是python3?@MadMike:这显然是python2。@MartijnPieters,尽管读者中的专家很清楚这一点,这仍然应该在相关问题中提及:是cp1250,但谢谢!不过,第二个答案如何与此相符?为什么u'kožušček'
会产生如此混乱的局面?感谢这些链接,我读了它们中的大多数(尤其是那些没有借口的链接),我遇到的问题只是shell->string部分。现在更清楚了。谢谢。如果这是在Windows命令提示符下,那么请知道该控制台在Unicode方面存在巨大的问题,至少在Python与Unicode的交互方式以及Microsoft所做的默认字体选择方面是如此。@5xum:您是否在使用空闲字体?有一个错误。Python2的其他部分也可能存在类似的错误,即读取Unicode文本部分也可能发生错误。如果运行:print u'ko\u017eu\u0161\xe8ek'
,您会看到什么?(注意:文本中没有非ascii字符)。注意:cp1250
很可能不是您的控制台编码(Windows使用di)
>>> u1=s1.decode(locale.getdefaultlocale()[1])
>>> u1
u'ko\u017eu\u0161\u010dek'
>>> print u1
kožušček
def setencoding():
"""Set the string encoding used by the Unicode implementation. The
default is 'ascii', but if you're willing to experiment, you can
change this."""
encoding = "ascii" # Default value set by _PyUnicode_Init()
if 0:
# Enable to support locale aware default string encodings.
import locale
loc = locale.getdefaultlocale()
if loc[1]:
encoding = loc[1]
if 0:
# Enable to switch off string to Unicode coercion and implicit
# Unicode to string conversion.
encoding = "undefined"
if encoding != "ascii":
# On Non-Unicode builds this will raise an AttributeError...
sys.setdefaultencoding(encoding) # Needs Python Unicode build !