¿Cómo puedo comprobar si una cadena es unicode o ascii?


¿Qué tengo que hacer en Python para averiguar qué codificación?

Author: TIMEX, 2011-02-14

10 answers

En Python 3, todas las cadenas son secuencias de caracteres Unicode. Hay un tipo bytes que contiene bytes sin procesar.

En Python 2, una cadena puede ser de tipo str o de tipo unicode. Puedes decir cuál usando código algo como esto:

def whatisthis(s):
    if isinstance(s, str):
        print "ordinary string"
    elif isinstance(s, unicode):
        print "unicode string"
    else:
        print "not a string"

Esto no distingue "Unicode o ASCII"; solo distingue tipos Python. Una cadena Unicode puede consistir en caracteres puramente en el rango ASCII, y una bytestring puede contener ASCII, Unicode codificado, o incluso datos no textuales.

 243
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-12 17:37:30

Solo hazlo

type(s)

Uno dirá unicode, el otro dirá str.

Puede manejarlos por separado usando isinstance, por ejemplo,

if isinstance(s, str):
    print 's is a string object'
elif isinstance(s, unicode):
    print 's is a unicode object'

O quieres decir que tienes un str, y estás tratando de averiguar si está codificado usando ASCII o UTF-8 o algo más?

En ese caso, prueba esto:

s.decode('ascii')

Si genera una excepción, la cadena no es 100% ASCII.

 99
Author: Mikel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-13 22:44:34

En python 3.x todas las cadenas son secuencias de caracteres Unicode. y hacer la comprobación de isinstance para str (que significa cadena unicode por defecto) debería ser suficiente.

isinstance(x, str)

Con respecto a python 2.x, La mayoría de las personas parecen estar usando una declaración if que tiene dos cheques. uno para str y otro para unicode.

Si desea comprobar si tiene un objeto 'tipo cadena' con una sola instrucción, puede hacer lo siguiente:

isinstance(x, basestring)
 39
Author: ThinkBonobo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 13:01:22

Unicode no es una codificación-para citar a Kumar McMillan:

Si ASCII, UTF-8 y otras cadenas de bytes son "text" ...

...entonces Unicode es "text-ness";

Es la forma abstracta del texto

Tener una lectura de McMillan Unicode En Python, Completamente Desmitificado charla de PyCon 2008, explica las cosas mucho mejor que la mayoría de las respuestas relacionadas en Stack Overflow.

 29
Author: Alex Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-21 14:12:19

Si su código necesita ser compatible con tanto Python 2 como Python 3, no puede usar directamente cosas como isinstance(s,bytes) o isinstance(s,unicode) sin envolverlas en try/except o en una prueba de versión de python, porque bytes no está definido en Python 2 y unicode no está definido en Python 3.

Hay algunas soluciones feas. Uno extremadamente feo es comparar el nombre del tipo, en lugar de comparar el tipo en sí. He aquí un ejemplo:

# 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)

Podría decirse que un poco menos fea solución es comprobar el número de versión de Python, por ejemplo:

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)

Ambos son impitónicos, y la mayoría de las veces probablemente hay una mejor manera.

 20
Author: Dave Burton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-14 12:33:05

Uso:

import six
if isinstance(obj, six. text_type)

Dentro de la biblioteca six representa como:

if PY3:
    string_types = str,
else:
    string_types = basestring,
 7
Author: madjardi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 23:48:37

Tenga en cuenta que en Python 3, no es realmente justo decir cualquiera de:

  • strs son UTFx para cualquier x (eg. UTF8)

  • strs son Unicode

  • strs son colecciones ordenadas de caracteres Unicode

El tipo str de Python es (normalmente) una secuencia de puntos de código Unicode, algunos de los cuales se asignan a caracteres.


Incluso en Python 3, no es tan sencillo responder a esta pregunta como te imaginas.

Una manera obvia de probar para cadenas compatibles con ASCII es por un intento de codificar:

"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)

El error distingue los casos.

En Python 3, incluso hay algunas cadenas que contienen puntos de código Unicode no válidos:

"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

Se utiliza el mismo método para distinguirlos.

 3
Author: Veedrac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-09 02:35:59

Podría usar Universal Encoding Detector, pero tenga en cuenta que solo le dará la mejor suposición, no la codificación real, porque es imposible saber la codificación de una cadena "abc", por ejemplo. Necesitará obtener información de codificación en otro lugar, por ejemplo, el protocolo HTTP usa encabezado Content-Type para eso.

 2
Author: Seb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-12 14:08:54

Esto puede ayudar a alguien más, comencé a probar el tipo de cadena de la variable s, pero para mi aplicación, tenía más sentido simplemente devolver s como utf-8. El proceso que llama a return_utf, entonces sabe con qué está tratando y puede manejar la cadena apropiadamente. El código no es prístino, pero pretendo que sea independiente de la versión de Python sin una prueba de versión o la importación de seis. Por favor, comente con mejoras en el código de ejemplo a continuación para ayudar a otras personas.

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
 2
Author: jfl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-13 10:10:37

Para la compatibilidad con py2/py3 simplemente use

import six if isinstance(obj, six.text_type)

 1
Author: Vishvajit Pathak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-28 11:56:41