【问题标题】:How do I check if a string is unicode or ascii?如何检查字符串是 unicode 还是 ascii?
【发布时间】:2011-06-26 14:49:36
【问题描述】:

我必须在 Python 中做什么才能确定字符串具有哪种编码?

【问题讨论】:

  • Unicode 不是编码。
  • @Johnsyweb 因为{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2

标签: python unicode encoding utf-8


【解决方案1】:

在 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,甚至是非文本数据。

【讨论】:

  • @ProsperousHeart:你可能正在使用 Python 3。
  • 注意:首先,你需要确认你运行的是Python2。如果您的代码设计为在 Python2 或 Python3 下运行,则需要先检查您的 Python 版本。
【解决方案2】:

如何判断一个对象是unicode字符串还是字节字符串

您可以使用typeisinstance

在 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


如何判断一个字节字符串是有效的 utf-8 还是 ascii

您可以拨打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)

【讨论】:

  • 仅供其他人参考-python 3中不存在str.decode。看来您必须unicode(s, "ascii")或其他东西
  • 对不起,我的意思是str(s, "ascii")
  • 这对于 python 3 不准确
  • @ProsperousHeart 更新以涵盖 Python 3。并尝试解释字节字符串和 unicode 字符串之间的区别。
  • decode() 方法的默认值为 'utf-8'。因此,如果您通过类“字节”调用此方法,例如,您会得到 print("utf8 content:", html.decode()) 的“OK”。
【解决方案3】:

在 python 3.x 中,所有字符串都是 Unicode 字符序列。并且对 str 进行 isinstance 检查(默认情况下表示 unicode 字符串)就足够了。

isinstance(x, str)

关于 python 2.x, 大多数人似乎都在使用一个有两个检查的 if 语句。一个用于 str,一个用于 unicode。

如果你想用一个语句检查你是否有一个“类似字符串”的对象,你可以执行以下操作:

isinstance(x, basestring)

【讨论】:

  • 这是错误的。在 Python 2.7 中,isinstance(u"x",basestring) 返回 True
  • @PythonNut:我相信这就是重点。使用 isinstance(x, basestring) 足以替代上述不同的双重测试。
  • 它在很多情况下很有用,但显然不是提问者的意思。
  • 这是问题的答案。所有其他人都误解了 OP 所说的内容,并给出了关于 Python 中类型检查的通用答案。
  • 不回答 OP 的问题。问题的标题(单独)可以解释为这个答案是正确的。但是,OP 在问题的描述中明确表示“找出哪个”,而这个答案并没有解决这个问题。
【解决方案4】:

Unicode 不是一种编码 - 引用 Kumar McMillan 的话:

如果 ASCII、UTF-8 和其他字节字符串是“文本”...

...那么 Unicode 是“文本性”;

是文本的抽象形式

阅读 McMillan 在 PyCon 2008 上的 Unicode In Python, Completely Demystified 演讲,它比 Stack Overflow 上的大多数相关答案更能解释问题。

【讨论】:

  • 这些幻灯片可能是我迄今为止遇到的关于 Unicode 的最佳介绍
【解决方案5】:

如果您的代码需要与 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_typesix.text_type进行测试
  • 您可以使用 type(s).__name__ 来探测类型名称。
  • 我不太确定那段代码的用例,除非存在逻辑错误。我认为python 2代码中应该有一个“不”。否则,您会将所有内容都转换为 Python 3 的 unicode 字符串,而 Python 2 则相反!
  • 是的,oligofren,它就是这么做的。标准的内部字符串是 Python 3 中的 Unicode 和 Python 2 中的 ASCII。因此代码 sn-ps 将文本转换为标准的内部字符串类型(无论是 Unicode 还是 ASCII)。
【解决方案6】:

使用:

import six
if isinstance(obj, six.text_type)

在六库中表示为:

if PY3:
    string_types = str,
else:
    string_types = basestring,

【讨论】:

  • 应该是if isinstance(obj, six.text_type) 。但是,是的,这是 imo 的正确答案。
  • 不回答 OP 的问题。问题的标题(单独)可以被解释为这个答案是正确的。但是,OP 在问题的描述中特别说“找出哪个”,而这个答案没有解决这个问题。
【解决方案7】:

请注意,在 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

使用相同的方法来区分它们。

【讨论】:

    【解决方案8】:

    这可能对其他人有所帮助,我开始测试变量 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
    

    【讨论】:

    • 你我的朋友应该得到正确的回应!我正在使用 python 3,但在找到这个宝藏之前我仍然遇到问题!
    【解决方案9】:

    您可以使用Universal Encoding Detector,但请注意,它只会给您最好的猜测,而不是实际的编码,因为不可能知道字符串“abc”的编码。您将需要在别处获取编码信息,例如 HTTP 协议为此使用 Content-Type 标头。

    【讨论】:

      【解决方案10】:

      在 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])
      

      为我工作,我希望为需要的人工作

      【讨论】:

        【解决方案11】:

        为了 py2/py3 的兼容性,只需使用

        import six if isinstance(obj, six.text_type)

        【讨论】:

          【解决方案12】:

          一种简单的方法是检查unicode 是否为内置函数。如果是这样,你在 Python 2 中,你的字符串将是一个字符串。为确保一切都在unicode 中,可以这样做:

          import builtins
          
          i = 'cats'
          if 'unicode' in dir(builtins):     # True in python 2, False in 3
            i = unicode(i)
          

          【讨论】:

            猜你喜欢
            • 2018-05-03
            • 1970-01-01
            • 2014-12-20
            • 1970-01-01
            • 1970-01-01
            • 2021-05-10
            • 2016-12-21
            • 2015-08-06
            • 1970-01-01
            相关资源
            最近更新 更多