A principal fonte de problemas que tive ao trabalhar com strings unicode é quando você mistura strings codificadas em utf-8 com strings Unicode.
Por exemplo, considere os seguintes scripts.
two.py
# encoding: utf-8
name = 'helló wörld from two'
one.py
# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name
O resultado da execução python one.py
é:
Traceback (most recent call last):
File "one.py", line 5, in <module>
print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)
Neste exemplo, two.name
é uma string codificada em utf-8 (não unicode), pois não foi importada unicode_literals
, e one.name
é uma string unicode. Quando você mistura os dois, o python tenta decodificar a string codificada (assumindo que seja ascii) e convertê-la para Unicode e falha. Funcionaria se você fizesse print name + two.name.decode('utf-8')
.
A mesma coisa pode acontecer se você codificar uma string e tentar misturá-las mais tarde. Por exemplo, isso funciona:
# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Resultado:
DEBUG: <html><body>helló wörld</body></html>
Mas depois de adicionar import unicode_literals
NÃO:
# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
html = html.encode('utf-8')
print 'DEBUG: %s' % html
Resultado:
Traceback (most recent call last):
File "test.py", line 6, in <module>
print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)
Ele falha porque 'DEBUG: %s'
é uma string Unicode e, portanto, o python tenta decodificar html
. Algumas maneiras de corrigir a impressão são: print str('DEBUG: %s') % html
ou print 'DEBUG: %s' % html.decode('utf-8')
.
Espero que isso ajude você a entender as possíveis dificuldades ao usar strings Unicode.
decode()
soluções em vez das soluçõesstr()
ouencode()
: quanto mais você usar objetos Unicode, mais claro será o código, já que o que você deseja é manipular strings de caracteres, não matrizes de bytes com uma codificação implícita externamente.when you mix utf-8 encoded strings with unicode ones
UTF-8 e Unicode não são 2 codificações diferentes; Unicode é um padrão e UTF-8 é uma das codificações que ele define.str
, o último é do tipounicode
. Sendo objetos diferentes, o problema pode surgir se você tentar somar / concatenar / interpolar elespython>=2.6
oupython==2.6
?Também no 2.6 (antes do python 2.6.5 RC1 +), os literais Unicode não funcionam bem com argumentos de palavra-chave (problema 4978 ):
O código a seguir, por exemplo, funciona sem unicode_literals, mas falha com TypeError:
keywords must be string
se unicode_literals for usado.fonte
Descobri que, se você adicionar a
unicode_literals
diretiva, também deve adicionar algo como:para a primeira ou segunda linha do arquivo .py. Caso contrário, linhas como:
resultar em um erro como:
fonte
# -*- coding: utf-8
é uma declaração virtualmente obrigatória, independentemente de você usarunicode_literals
ou não-*-
não é necessário; se você estivesse indo para o caminho compatível com emacs, acho que você precisaria-*- encoding: utf-8 -*-
(veja o-*-
no final também). Tudo que você precisa écoding: utf-8
(ou mesmo em=
vez de:
).from __future__ import unicode_literals
.# -*- coding: utf-8 -*-
"codificação" (não "codificação" ou "codificação de arquivo" ou qualquer outra coisa - o Python apenas procura "codificação" independentemente de qualquer prefixo).Também leve em consideração que
unicode_literal
isso afetará,eval()
mas nãorepr()
(um comportamento assimétrico que imho é um bug), ou sejaeval(repr(b'\xa4'))
, não será igualb'\xa4'
(como seria com Python 3).Idealmente, o código a seguir seria uma invariante, que sempre deve funcionar, para todas as combinações de uso de
unicode_literals
Python {2.7, 3.x}:A segunda afirmação funciona, uma vez que
repr('\xa4')
avaliau'\xa4'
no Python 2.7.fonte
repr
para regenerar um objeto. Arepr
documentação afirma claramente que isso não é um requisito. Na minha opinião, isso relegarepr
a algo útil apenas para depuração.Há mais.
Existem bibliotecas e builtins que esperam strings que não toleram Unicode.
Dois exemplos:
construídas em:
(ligeiramente esótico) não funciona com unicode_literals: type () espera uma string.
biblioteca:
não funciona: a biblioteca wx pubsub espera um tipo de mensagem de string.
O primeiro é esotérico e facilmente corrigido com
mas o último é devastador se seu código estiver cheio de chamadas para pub.sendMessage () (que é o meu).
Droga, hein?!?
fonte
class Meta:
deve serb'field_name'
Clique levantará exceções unicode em todo o lugar se qualquer módulo que foi
from __future__ import unicode_literals
importado para onde você usaclick.echo
. É um pesadelo…fonte