Quero verificar se uma string está em ASCII ou não.
Estou ciente ord()
, no entanto, quando tento ord('é')
, tenho TypeError: ord() expected a character, but string of length 2 found
. Eu entendi que isso é causado pela maneira como construí o Python (como explicado na ord()
documentação de ).
Existe outra maneira de verificar?
Respostas:
fonte
ord(c) < 128
é infinitamente mais legível e intuitivo do quec <= "\x7F"
Eu acho que você não está fazendo a pergunta certa--
Uma cadeia de caracteres em python não possui propriedades correspondentes a 'ascii', utf-8 ou qualquer outra codificação. A fonte da sua string (se você a lê em um arquivo, entrada em um teclado etc.) pode ter codificado uma string unicode em ascii para produzir sua string, mas é aí que você precisa obter uma resposta.
Talvez a pergunta que você possa fazer seja: "Essa string é o resultado da codificação de uma string unicode em ascii?" - Isso você pode responder tentando:
fonte
str
no Python 2,bytes
no Python 3).str
em qualquer codificação ISO precisaria ser codificada para Unicode primeiro. A resposta deve entrar nisso.s.decode('ascii') if isinstance(s, bytes) else s.encode('ascii')
no Python 3. A entrada do OP é um bytestring'é'
(sintaxe do Python 2, o Python 3 não havia sido lançado no momento) e, portanto,.decode()
está correto.str
no Python 2 é um bytestring. É correto usar.decode('ascii')
para descobrir se todos os bytes estão no intervalo ascii.Maneira Python 3:
Para verificar, passe na sequência de teste:
fonte
isascii
agora é uma função que você passa uma string:isascii('somestring')
==True
eisascii('àéç')
==False
try: s.encode('ascii'); return True
except UnicodeEncodeError: return False
(como acima, mas codificando, como as strings são Unicode no Python 3). Essa resposta também levanta um erro no Python 3 quando você tem substitutos (por exemplo,isascii('\uD800')
gera um erro em vez de voltarFalse
)Novo no Python 3.7 ( bpo32677 )
Chega de verificações ascii cansativas / ineficientes nas strings, novo método
str
/bytes
/bytearray
interno -.isascii()
verificará se as strings são ascii.fonte
"\x03".isascii()
também é verdadeiro. A documentação diz que isso apenas verifica se todos os caracteres estão abaixo do ponto de código 128 (0-127). Se você também quer evitar caracteres de controle, você vai precisar de:text.isascii() and text.isprintable()
. Apenas usarisprintable
por si só também não é suficiente, pois considerará um caractere como ¿imprimível (corretamente), mas não está dentro da seção imprimível ascii, portanto, você deve verificar os dois se desejar os dois. Ainda outro problema: os espaços são considerados imprimíveis, as guias e as novas linhas não.Encontrei algo assim recentemente - para referência futura
com o qual você pode usar:
fonte
{'confidence': 0.99, 'encoding': 'EUC-JP'}
(que neste caso era completamente errado)Vincent Marchetti tem a idéia certa, mas
str.decode
foi preterido no Python 3. No Python 3, você pode fazer o mesmo teste comstr.encode
:Observe que a exceção que você deseja capturar também mudou de
UnicodeDecodeError
paraUnicodeEncodeError
.fonte
bytes
digite no Python 3 que não possui.encode()
método)..decode()
na resposta de @Vincent Marchetti está correta .'é'
houve um desvio na época.Sua pergunta está incorreta; o erro que você vê não é resultado de como você criou python, mas de uma confusão entre cadeias de bytes e cadeias unicode.
Cadeias de bytes (por exemplo, "foo", ou 'bar', na sintaxe python) são sequências de octetos; números de 0 a 255. Strings Unicode (por exemplo, u "foo" ou u'bar ') são sequências de pontos de código unicode; números de 0 a 11202064. Mas você parece estar interessado no caractere é, que (em seu terminal) é uma sequência de vários bytes que representa um único caractere.
Em vez de
ord(u'é')
, tente o seguinte:Isso indica qual sequência de pontos de código "é" representa. Pode dar a você [233], ou pode dar a você [101, 770].
Em vez de
chr()
reverter isso, existeunichr()
:Na verdade, esse caractere pode ser representado como um ou vários "pontos de código" unicode, que representam grafos ou caracteres. É "e com um sotaque agudo (isto é, ponto de código 233)" ou "e" (ponto de código 101), seguido por "um sotaque agudo do caractere anterior" (ponto de código 770). Portanto, esse mesmo caractere exato pode ser apresentado como a estrutura de dados Python
u'e\u0301'
ouu'\u00e9'
.Na maioria das vezes, você não precisa se preocupar com isso, mas isso pode se tornar um problema se você estiver iterando sobre uma cadeia unicode, pois a iteração funciona por ponto de código, não por caractere decomponível. Em outras palavras,
len(u'e\u0301') == 2
elen(u'\u00e9') == 1
. Se isso lhe interessa, você pode converter entre formulários compostos e decompostos usandounicodedata.normalize
.O Glossário Unicode pode ser um guia útil para entender alguns desses problemas, apontando como cada termo específico se refere a uma parte diferente da representação do texto, o que é muito mais complicado do que muitos programadores imaginam.
fonte
Que tal fazer isso?
fonte
Encontrei essa pergunta ao tentar determinar como usar / codificar / decodificar uma string cuja codificação eu não tinha certeza (e como escapar / converter caracteres especiais nessa string).
Meu primeiro passo deveria ter sido verificar o tipo da string - eu não sabia que podia obter bons dados sobre a formatação dos tipos. Esta resposta foi muito útil e chegou à raiz real dos meus problemas.
Se você está sendo grosseiro e persistente
particularmente quando você está codificando, verifique se não está tentando unicode () uma string que já é unicode - por algum motivo terrível, você recebe erros de codec ascii. (Veja também a receita do Python Kitchen e os documentos do Python tutoriais de para entender melhor o quão terrível isso pode ser.)
Eventualmente, eu determinei que o que eu queria fazer era o seguinte:
Também útil na depuração foi definir a codificação padrão no meu arquivo para utf-8 (coloque isso no início do seu arquivo python):
Isso permite que você teste caracteres especiais ('àéç') sem precisar usar seus escapes unicode (u '\ xe0 \ xe9 \ xe7').
fonte
Para melhorar a solução de Alexander do Python 2.6 (e no Python 3.x), você pode usar o módulo auxiliar curses.ascii e a função curses.ascii.isascii () ou várias outras funções: https://docs.python.org/2.6/ library / curses.ascii.html
fonte
curses.ascii
Você pode usar a biblioteca de expressões regulares que aceita a definição padrão [[: ASCII:]] do Posix.
fonte
Uma picada (
str
-tipo) no Python é uma série de bytes. Não tem como dizer, apenas olhando para a string, se essa série de bytes representa uma string ascii, uma string em um conjunto de caracteres de 8 bits como ISO-8859-1 ou uma string codificada com UTF-8 ou UTF-16 ou qualquer outra coisa. .No entanto, se você souber a codificação usada, poderá
decode
colocar a string em uma string unicode e, em seguida, usar uma expressão regular (ou um loop) para verificar se ela contém caracteres fora do intervalo que você está preocupado.fonte
Como a resposta de @ RogerDahl, mas é mais eficiente dar um curto-circuito negando a classe de personagem e usando a pesquisa em vez de
find_all
oumatch
.Imagino que uma expressão regular seja bem otimizada para isso.
fonte
Para incluir uma sequência vazia como ASCII, altere
+
para*
.fonte
Para evitar falhas no código, talvez você queira usar um
try-except
para capturarTypeErrors
Por exemplo
fonte
try
invólucro é completamente inútil. Se"¶"
for uma string Unicode,ord("¶")
funcionará e, se não for (Python 2),for c in s
a decomporá em bytesord
, continuando a funcionar.Eu uso o seguinte para determinar se a seqüência de caracteres é ascii ou unicode:
Em seguida, basta usar um bloco condicional para definir a função:
fonte
is_ascii(u'i am ascii')
. Mesmo que as letras e os espaços sejam definitivamente ASCII, isso ainda retornaFalse
porque forçamos a string a serunicode
.