Respuestas:
En Python 3, todas las cadenas son secuencias de caracteres Unicode. Hay un bytes
tipo que contiene bytes sin procesar.
En Python 2, una cadena puede ser de tipo str
o de tipo unicode
. Puedes decir qué código usando 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 los tipos de Python. Una cadena Unicode puede consistir en puramente caracteres en el rango ASCII, y una cadena de bytes puede contener ASCII, Unicode codificado o incluso datos no textuales.
Puedes usar type
oisinstance
.
En Python 2:
>>> type(u'abc') # Python 2 unicode string literal
<type 'unicode'>
>>> type('abc') # Python 2 byte string literal
<type 'str'>
En Python 2, str
es solo una secuencia de bytes. Python no sabe cuál es su codificación. El unicode
tipo es la forma más segura de almacenar texto. Si quieres entender esto más, te recomiendo http://farmdev.com/talks/unicode/ .
En Python 3:
>>> type('abc') # Python 3 unicode string literal
<class 'str'>
>>> type(b'abc') # Python 3 byte string literal
<class 'bytes'>
En Python 3, str
es como Python 2 unicode
y se usa para almacenar texto. Lo que se llamó str
en Python 2 se llama bytes
en Python 3.
Puede llamar decode
. Si genera una excepción UnicodeDecodeError, no fue válida.
>>> 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")
o algo así
str(s, "ascii")
En python 3.x todas las cadenas son secuencias de caracteres Unicode. y hacer la verificación 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 verificaciones. uno para str y otro para unicode.
Sin embargo, si desea verificar si tiene un objeto 'tipo cadena' con una sola declaración, puede hacer lo siguiente:
isinstance(x, basestring)
isinstance(u"x",basestring)
regresa True
.
Unicode no es una codificación, para citar a Kumar McMillan:
Si ASCII, UTF-8 y otras cadenas de bytes son "texto" ...
... entonces Unicode es "text-ness";
es la forma abstracta de texto
Lea el Unicode In Python de McMillan , una charla completamente desmitificada de PyCon 2008, que explica las cosas mucho mejor que la mayoría de las respuestas relacionadas en Stack Overflow.
Si su código necesita ser compatible tanto con Python 2 como con Python 3, no puede usar directamente cosas como isinstance(s,bytes)
o isinstance(s,unicode)
sin envolverlas en try / except o una prueba de versión de python, porquebytes
no está definido en Python 2 yunicode
no está definido en Python 3 .
Hay algunas soluciones feas. Una muy fea es comparar el nombre del tipo, en lugar de comparar el tipo en sí. Aquí hay 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)
Una solución alternativa un poco menos fea es verificar 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)
Ambas son poco pitónicas, y la mayoría de las veces probablemente haya una mejor manera.
six
, y probar contra six.binary_type
ysix.text_type
utilizar:
import six
if isinstance(obj, six.text_type)
dentro de las seis bibliotecas se representa como:
if PY3:
string_types = str,
else:
string_types = basestring,
if isinstance(obj, six.text_type)
. Pero sí, esta es la respuesta correcta.
Tenga en cuenta que en Python 3, no es realmente justo decir nada de:
str
s son UTFx para cualquier x (por ejemplo, UTF8)
str
s son Unicode
str
s son colecciones ordenadas de caracteres Unicode
El str
tipo 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 simple responder esta pregunta como te puedas imaginar.
Una forma obvia de probar cadenas compatibles con ASCII es mediante un intento de codificación:
"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.
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, luego sabe de qué se trata y puede manejar la cadena de manera apropiada. El código no es prístino, pero tengo la intención de que sea independiente de la versión de Python sin una prueba de versión o importando seis. Comente con las mejoras al código de muestra 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
Podría usar el Detector de codificación universal , pero tenga en cuenta que solo le dará una 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 utiliza el encabezado Content-Type para eso.
Para compatibilidad con py2 / py3 simplemente use
import six
if isinstance(obj, six.text_type)
Un enfoque simple es verificar si unicode
es una función incorporada. Si es así, estás en Python 2 y tu cadena será una cadena. Para asegurarse de que todo está en unicode
uno, puede hacer:
import builtins
i = 'cats'
if 'unicode' in dir(builtins): # True in python 2, False in 3
i = unicode(i)