【发布时间】:2011-06-26 14:49:36
【问题描述】:
我必须在 Python 中做什么才能确定字符串具有哪种编码?
【问题讨论】:
-
Unicode 不是编码。
-
@Johnsyweb 因为
{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
标签: python unicode encoding utf-8
我必须在 Python 中做什么才能确定字符串具有哪种编码?
【问题讨论】:
{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
标签: python unicode encoding utf-8
在 Python 3 中,所有字符串都是 Unicode 字符序列。有一个 bytes 类型保存原始字节。
在 Python 2 中,字符串可以是 str 类型或 unicode 类型。您可以使用类似这样的代码来判断哪个:
def whatisthis(s):
if isinstance(s, str):
print "ordinary string"
elif isinstance(s, unicode):
print "unicode string"
else:
print "not a string"
这不区分“Unicode 或 ASCII”;它只区分 Python 类型。一个 Unicode 字符串可能由纯 ASCII 范围内的字符组成,而一个字节串可能包含 ASCII、编码的 Unicode,甚至是非文本数据。
【讨论】:
您可以使用type 或isinstance。
在 Python 2 中:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
在 Python 2 中,str 只是一个字节序列。 Python不知道什么
它的编码是。 unicode 类型是更安全的文本存储方式。
如果你想了解更多,我推荐http://farmdev.com/talks/unicode/。
在 Python 3 中:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
在 Python 3 中,str 类似于 Python 2 的 unicode,用于
存储文本。在 Python 2 中称为 str 在 Python 3 中称为 bytes。
您可以拨打decode。如果它引发 UnicodeDecodeError 异常,则它无效。
>>> u_umlaut = b'\xc3\x9c' # UTF-8 representation of the letter 'Ü'
>>> u_umlaut.decode('utf-8')
u'\xdc'
>>> u_umlaut.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
【讨论】:
unicode(s, "ascii")或其他东西
str(s, "ascii")
print("utf8 content:", html.decode()) 的“OK”。
在 python 3.x 中,所有字符串都是 Unicode 字符序列。并且对 str 进行 isinstance 检查(默认情况下表示 unicode 字符串)就足够了。
isinstance(x, str)
关于 python 2.x, 大多数人似乎都在使用一个有两个检查的 if 语句。一个用于 str,一个用于 unicode。
如果你想用一个语句检查你是否有一个“类似字符串”的对象,你可以执行以下操作:
isinstance(x, basestring)
【讨论】:
isinstance(u"x",basestring) 返回 True。
Unicode 不是一种编码 - 引用 Kumar McMillan 的话:
如果 ASCII、UTF-8 和其他字节字符串是“文本”...
...那么 Unicode 是“文本性”;
是文本的抽象形式
阅读 McMillan 在 PyCon 2008 上的 Unicode In Python, Completely Demystified 演讲,它比 Stack Overflow 上的大多数相关答案更能解释问题。
【讨论】:
如果您的代码需要与 Python 2 和 Python 3 兼容,则不能直接使用 isinstance(s,bytes) 或 isinstance(s,unicode) 之类的东西,而无需将它们包装在 try/except 或 a python版本测试,因为bytes在Python 2中未定义,unicode在Python 3中未定义。
有一些丑陋的解决方法。一个极其丑陋的方法是比较类型的name,而不是比较类型本身。这是一个例子:
# convert bytes (python 3) or unicode (python 2) to str
if str(type(s)) == "<class 'bytes'>":
# only possible in Python 3
s = s.decode('ascii') # or s = str(s)[2:-1]
elif str(type(s)) == "<type 'unicode'>":
# only possible in Python 2
s = str(s)
一个可以说不那么难看的解决方法是检查 Python 版本号,例如:
if sys.version_info >= (3,0,0):
# for Python 3
if isinstance(s, bytes):
s = s.decode('ascii') # or s = str(s)[2:-1]
else:
# for Python 2
if isinstance(s, unicode):
s = str(s)
这些都不是pythonic,而且大多数时候可能有更好的方法。
【讨论】:
six,并针对six.binary_type和six.text_type进行测试
使用:
import six
if isinstance(obj, six.text_type)
在六库中表示为:
if PY3:
string_types = str,
else:
string_types = basestring,
【讨论】:
if isinstance(obj, six.text_type) 。但是,是的,这是 imo 的正确答案。
请注意,在 Python 3 上,说以下任何一个都不公平:
strs 是任何 x 的 UTFx(例如 UTF8)
strs 是 Unicode
strs 是 Unicode 字符的有序集合
Python 的str 类型(通常)是一系列 Unicode 代码点,其中一些映射到字符。
即使在 Python 3 上,回答这个问题也没有你想象的那么简单。
测试 ASCII 兼容字符串的一个明显方法是尝试编码:
"Hello there!".encode("ascii")
#>>> b'Hello there!'
"Hello there... ☃!".encode("ascii")
#>>> Traceback (most recent call last):
#>>> File "", line 4, in <module>
#>>> UnicodeEncodeError: 'ascii' codec can't encode character '\u2603' in position 15: ordinal not in range(128)
错误区分大小写。
在 Python 3 中,甚至有一些字符串包含无效的 Unicode 代码点:
"Hello there!".encode("utf8")
#>>> b'Hello there!'
"\udcc3".encode("utf8")
#>>> Traceback (most recent call last):
#>>> File "", line 19, in <module>
#>>> UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 0: surrogates not allowed
使用相同的方法来区分它们。
【讨论】:
这可能对其他人有所帮助,我开始测试变量 s 的字符串类型,但对于我的应用程序,将 s 简单地返回为 utf-8 更有意义。调用 return_utf 的进程知道它正在处理什么并可以适当地处理字符串。代码不是原始的,但我打算让它与 Python 版本无关,无需版本测试或导入六个。请评论以下示例代码的改进以帮助其他人。
def return_utf(s):
if isinstance(s, str):
return s.encode('utf-8')
if isinstance(s, (int, float, complex)):
return str(s).encode('utf-8')
try:
return s.encode('utf-8')
except TypeError:
try:
return str(s).encode('utf-8')
except AttributeError:
return s
except AttributeError:
return s
return s # assume it was already utf-8
【讨论】:
您可以使用Universal Encoding Detector,但请注意,它只会给您最好的猜测,而不是实际的编码,因为不可能知道字符串“abc”的编码。您将需要在别处获取编码信息,例如 HTTP 协议为此使用 Content-Type 标头。
【讨论】:
在 Python-3 中,我必须了解字符串是像 b='\x7f\x00\x00\x01' 还是 b='127.0.0.1' 我的解决方案是这样的:
def get_str(value):
str_value = str(value)
if str_value.isprintable():
return str_value
return '.'.join(['%d' % x for x in value])
为我工作,我希望为需要的人工作
【讨论】:
为了 py2/py3 的兼容性,只需使用
import six
if isinstance(obj, six.text_type)
【讨论】:
一种简单的方法是检查unicode 是否为内置函数。如果是这样,你在 Python 2 中,你的字符串将是一个字符串。为确保一切都在unicode 中,可以这样做:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)
【讨论】: