Mais importante, por que você deveria se importar?
Johnsyweb 14/02
@Johnsyweb Por causa de{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
alex
Respostas:
295
No Python 3, todas as strings são seqüências de caracteres Unicode. Há um bytestipo que contém bytes brutos.
No Python 2, uma string pode ser do tipo strou do tipo unicode. Você pode dizer qual código usando algo parecido com isto:
def whatisthis(s):if isinstance(s, str):print"ordinary string"elif isinstance(s, unicode):print"unicode string"else:print"not a string"
Isso não distingue "Unicode ou ASCII"; apenas distingue os tipos Python. Uma cadeia de caracteres Unicode pode consistir em caracteres puramente no intervalo ASCII, e uma cadeia de bytes pode conter dados ASCII, Unicode codificados ou mesmo não textuais.
No Python 2, stré apenas uma sequência de bytes. Python não sabe qual é a sua codificação. O unicodetipo é a maneira mais segura de armazenar texto. Se você quiser entender mais isso, recomendo http://farmdev.com/talks/unicode/ .
No Python 3, stré como o Python 2 unicodee é usado para armazenar texto. O que foi chamado strno Python 2 é chamado bytesno Python 3.
Como saber se uma sequência de bytes é válida utf-8 ou ascii
Você pode ligar decode. Se gerar uma exceção UnicodeDecodeError, não será válido.
>>> 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)
Apenas para referência de outras pessoas - str.decode não não existe em python 3. Parece que você tem que unicode(s, "ascii")ou algo
Sombra
3
Desculpe, eu quis dizerstr(s, "ascii")
Sombra
1
Isso não é preciso para python 3
ProsperousHeart
2
@ProsperousHeart Atualizado para cobrir o Python 3. E para tentar explicar a diferença entre bytestrings e unicode.
Mikel
44
No python 3.x, todas as strings são seqüências de caracteres Unicode. e fazer a verificação isinstance para str (que significa string unicode por padrão) deve ser suficiente.
isinstance(x, str)
Com relação ao python 2.x, a maioria das pessoas parece estar usando uma instrução if com duas verificações. um para str e outro para unicode.
Se você quiser verificar se possui um objeto 'semelhante a uma string', com apenas uma instrução, faça o seguinte:
Isto é falso. No Python 2.7 isinstance(u"x",basestring)retorna True.
precisa saber é o seguinte
11
@ PythonNut: Eu acredito que esse era o ponto. O uso de isinstance (x, basestring) é suficiente para substituir os distintos testes duplos acima.
KQ.
5
É útil em muitos casos, mas evidentemente não é o que o questionador quis dizer.
mhsmith
3
Essa é a resposta para a pergunta. Todos os outros entenderam mal o que o OP disse e deram respostas genéricas sobre a verificação de tipos no Python.
Fiatjaf 11/04/2015
1
Não responde à pergunta do OP. O título da pergunta (sozinho) PODE ser interpretado de forma que esta resposta esteja correta. No entanto, o OP diz especificamente "descobrir qual" na descrição da pergunta, e esta resposta não aborda isso.
MD004
31
Unicode não é uma codificação - para citar Kumar McMillan:
Se ASCII, UTF-8 e outras cadeias de bytes são "texto" ...
... então Unicode é "text-ness";
é a forma abstrata do texto
Leia a palestra Unicode In Python, completamente desmistificada do PyCon 2008, da McMillan, que explica as coisas muito melhor do que a maioria das respostas relacionadas ao Stack Overflow.
Esses slides são provavelmente a melhor introdução ao Unicode que eu já vi até agora
Jonny
23
Se as suas necessidades de código para ser compatível com ambos Python 2 e Python 3, você não pode usar diretamente coisas como isinstance(s,bytes)ou isinstance(s,unicode)sem colocá-los em qualquer try / exceto ou um teste de versão python, porque bytesé indefinido em Python 2 e unicodeé indefinido em Python 3 .
Existem algumas soluções feias. Uma coisa extremamente feia é comparar o nome do tipo, em vez de comparar o próprio tipo. Aqui está um exemplo:
# convert bytes (python 3) or unicode (python 2) to strif 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)
Uma solução indiscutivelmente um pouco menos feia é verificar o número da versão do Python, por exemplo:
if sys.version_info >=(3,0,0):# for Python 3if isinstance(s, bytes):
s = s.decode('ascii')# or s = str(s)[2:-1]else:# for Python 2if isinstance(s, unicode):
s = str(s)
Ambos são não-tônicos, e na maioria das vezes provavelmente existe uma maneira melhor.
A melhor maneira é provavelmente usar sixe testar contra six.binary_typeesix.text_type
Ian Clelland
1
Você pode usar o (s) tipo (s) .__ name__ para pesquisar nomes de tipo.
Paulo Freitas
Não tenho muita certeza do caso de uso desse bit de código, a menos que haja um erro lógico. Eu acho que deveria haver um "não" no código python 2. Caso contrário, você está convertendo tudo em cadeias unicode para Python 3 e o oposto para Python 2!
precisa
Sim, oligofren, é o que faz. As cadeias internas padrão são Unicode no Python 3 e ASCII no Python 2. Portanto, os trechos de código convertem texto em tipo de cadeia interna padrão (seja Unicode ou ASCII).
Dave Burton
12
usar:
import six
if isinstance(obj, six.text_type)
dentro da biblioteca seis é representado como:
if PY3:
string_types = str,else:
string_types = basestring,
deveria ser if isinstance(obj, six.text_type) . Mas sim, esta é a resposta correta.
karantan
Não responde à pergunta do OP. O título da pergunta (sozinho) PODE ser interpretado de forma que esta resposta esteja correta. No entanto, o OP diz especificamente "descobrir qual" na descrição da pergunta, e esta resposta não aborda isso.
MD004
4
Observe que no Python 3, não é realmente justo dizer um dos seguintes:
strs são UTFx para qualquer x (por exemplo, UTF8)
strs são Unicode
strs são coleções ordenadas de caracteres Unicode
O strtipo de Python é (normalmente) uma sequência de pontos de código Unicode, alguns dos quais são mapeados para caracteres.
Mesmo no Python 3, não é tão simples responder a essa pergunta como você pode imaginar.
Uma maneira óbvia de testar cadeias compatíveis com ASCII é através de uma tentativa de codificação:
"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)
O erro distingue os casos.
No Python 3, existem até algumas strings que contêm pontos de código Unicode invá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
Isso pode ajudar outra pessoa. Comecei a testar o tipo de string da variável s, mas, para meu aplicativo, fazia mais sentido simplesmente retornar s como utf-8. O processo que chama return_utf, então sabe com o que está lidando e pode manipular a sequência adequadamente. O código não é puro, mas pretendo que ele seja independente da versão Python sem um teste de versão ou sem importar seis. Comente com melhorias no código de exemplo abaixo para ajudar outras pessoas.
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')exceptTypeError:try:return str(s).encode('utf-8')exceptAttributeError:return s
exceptAttributeError:return s
return s # assume it was already utf-8
Você meu amigo merece ser a resposta correta! Estou usando o python 3 e ainda estava tendo problemas até encontrar esse tesouro!
MNSR
2
Você pode usar o Universal Encoding Detector , mas lembre-se de que ele fornecerá o melhor palpite, não a codificação real, porque é impossível saber a codificação de uma string "abc", por exemplo. Você precisará obter informações de codificação em outro lugar, por exemplo, o protocolo HTTP usa o cabeçalho Content-Type para isso.
Uma abordagem simples é verificar se unicodeé uma função interna. Nesse caso, você está no Python 2 e sua string será uma string. Para garantir que tudo está em unicodeum pode fazer:
import builtins
i ='cats'if'unicode'in dir(builtins):# True in python 2, False in 3
i = unicode(i)
{UnicodeDecodeError} 'ascii' codec can't decode byte 0xc2
Respostas:
No Python 3, todas as strings são seqüências de caracteres Unicode. Há um
bytes
tipo que contém bytes brutos.No Python 2, uma string pode ser do tipo
str
ou do tipounicode
. Você pode dizer qual código usando algo parecido com isto:Isso não distingue "Unicode ou ASCII"; apenas distingue os tipos Python. Uma cadeia de caracteres Unicode pode consistir em caracteres puramente no intervalo ASCII, e uma cadeia de bytes pode conter dados ASCII, Unicode codificados ou mesmo não textuais.
fonte
Como saber se um objeto é uma string unicode ou byte
Você pode usar
type
ouisinstance
.No Python 2:
No Python 2,
str
é apenas uma sequência de bytes. Python não sabe qual é a sua codificação. Ounicode
tipo é a maneira mais segura de armazenar texto. Se você quiser entender mais isso, recomendo http://farmdev.com/talks/unicode/ .No Python 3:
No Python 3,
str
é como o Python 2unicode
e é usado para armazenar texto. O que foi chamadostr
no Python 2 é chamadobytes
no Python 3.Como saber se uma sequência de bytes é válida utf-8 ou ascii
Você pode ligar
decode
. Se gerar uma exceção UnicodeDecodeError, não será válido.fonte
unicode(s, "ascii")
ou algostr(s, "ascii")
No python 3.x, todas as strings são seqüências de caracteres Unicode. e fazer a verificação isinstance para str (que significa string unicode por padrão) deve ser suficiente.
Com relação ao python 2.x, a maioria das pessoas parece estar usando uma instrução if com duas verificações. um para str e outro para unicode.
Se você quiser verificar se possui um objeto 'semelhante a uma string', com apenas uma instrução, faça o seguinte:
fonte
isinstance(u"x",basestring)
retornaTrue
.Unicode não é uma codificação - para citar Kumar McMillan:
Leia a palestra Unicode In Python, completamente desmistificada do PyCon 2008, da McMillan, que explica as coisas muito melhor do que a maioria das respostas relacionadas ao Stack Overflow.
fonte
Se as suas necessidades de código para ser compatível com ambos Python 2 e Python 3, você não pode usar diretamente coisas como
isinstance(s,bytes)
ouisinstance(s,unicode)
sem colocá-los em qualquer try / exceto ou um teste de versão python, porquebytes
é indefinido em Python 2 eunicode
é indefinido em Python 3 .Existem algumas soluções feias. Uma coisa extremamente feia é comparar o nome do tipo, em vez de comparar o próprio tipo. Aqui está um exemplo:
Uma solução indiscutivelmente um pouco menos feia é verificar o número da versão do Python, por exemplo:
Ambos são não-tônicos, e na maioria das vezes provavelmente existe uma maneira melhor.
fonte
six
e testar contrasix.binary_type
esix.text_type
usar:
dentro da biblioteca seis é representado como:
fonte
if isinstance(obj, six.text_type)
. Mas sim, esta é a resposta correta.Observe que no Python 3, não é realmente justo dizer um dos seguintes:
str
s são UTFx para qualquer x (por exemplo, UTF8)str
s são Unicodestr
s são coleções ordenadas de caracteres UnicodeO
str
tipo de Python é (normalmente) uma sequência de pontos de código Unicode, alguns dos quais são mapeados para caracteres.Mesmo no Python 3, não é tão simples responder a essa pergunta como você pode imaginar.
Uma maneira óbvia de testar cadeias compatíveis com ASCII é através de uma tentativa de codificação:
O erro distingue os casos.
No Python 3, existem até algumas strings que contêm pontos de código Unicode inválidos:
O mesmo método para distingui-los é usado.
fonte
Isso pode ajudar outra pessoa. Comecei a testar o tipo de string da variável s, mas, para meu aplicativo, fazia mais sentido simplesmente retornar s como utf-8. O processo que chama return_utf, então sabe com o que está lidando e pode manipular a sequência adequadamente. O código não é puro, mas pretendo que ele seja independente da versão Python sem um teste de versão ou sem importar seis. Comente com melhorias no código de exemplo abaixo para ajudar outras pessoas.
fonte
Você pode usar o Universal Encoding Detector , mas lembre-se de que ele fornecerá o melhor palpite, não a codificação real, porque é impossível saber a codificação de uma string "abc", por exemplo. Você precisará obter informações de codificação em outro lugar, por exemplo, o protocolo HTTP usa o cabeçalho Content-Type para isso.
fonte
Para compatibilidade com py2 / py3, basta usar
import six if isinstance(obj, six.text_type)
fonte
Uma abordagem simples é verificar se
unicode
é uma função interna. Nesse caso, você está no Python 2 e sua string será uma string. Para garantir que tudo está emunicode
um pode fazer:fonte