Ao canalizar a saída de um programa Python, o interpretador Python fica confuso sobre a codificação e o define como Nenhum. Isso significa um programa como este:
# -*- coding: utf-8 -*-
print u"åäö"
funcionará bem quando executado normalmente, mas falhará com:
UnicodeEncodeError: o codec 'ascii' não pode codificar o caractere u '\ xa0' na posição 0: ordinal fora do intervalo (128)
quando usado em uma sequência de tubulação.
Qual é a melhor maneira de fazer isso funcionar na tubulação? Posso apenas dizer a ele para usar a codificação que seja o shell / sistema de arquivos / o que estiver usando?
As sugestões que eu vi até agora são modificar o site.py diretamente ou codificar a codificação padrão usando este hack:
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
Existe uma maneira melhor de fazer a tubulação funcionar?
chcp 65001
antes de executar seu script. Isso pode ter problemas, mas geralmente ajuda e não requer muita digitação (menos queset PYTHONIOENCODING=utf_8
).setx PYTHONENCODING utf-8
torná-lo permanente, se você quiser salvar a digitação.Respostas:
Seu código funciona quando executado em um script porque o Python codifica a saída para qualquer codificação que seu aplicativo de terminal estiver usando. Se você estiver usando um encanamento, deverá codificá-lo.
Uma regra prática é: sempre use Unicode internamente. Decodifique o que você recebe e codifique o que você envia.
Outro exemplo didático é um programa Python para converter entre ISO-8859-1 e UTF-8, tornando tudo maiúsculo.
Definir a codificação padrão do sistema é uma má idéia, porque alguns módulos e bibliotecas que você usa podem confiar no fato de serem ASCII. Não faça isso.
fonte
sys.stdout
parece ser uma maneira mais agradável.PYTHONIOENCODING
se você está redirecionando stdout do script em Python 2.Primeiro, com relação a esta solução:
Não é prático imprimir explicitamente com uma determinada codificação sempre. Isso seria repetitivo e propenso a erros.
Uma solução melhor é mudar
sys.stdout
no início do seu programa, codificar com uma codificação selecionada. Aqui está uma solução que encontrei no Python: Como o sys.stdout.encoding é escolhido? , em particular um comentário de "toka":fonte
def myprint(unicodeobj): print unicodeobj.encode('utf-8')
- você detecta automaticamente a codificação do terminal inspecionandosys.stdout.encoding
, mas deve considerar o caso em que estáNone
(por exemplo, ao redirecionar a saída para um arquivo) então você precisa de uma função separada de qualquer maneira.Você pode tentar alterar a variável de ambiente "PYTHONIOENCODING" para "utf_8". Eu escrevi uma página no meu calvário com este problema .
Tl; dr da postagem do blog:
da-te
fonte
sys.stdout = codecs.getwriter(encoding)(sys.stdout)
. Isso pode ser feito no programa python, para que o usuário não seja forçado a definir uma variável env.PYTHONIOENCODING
funciona. Como os bytes são interpretados como um texto é definido pelo ambiente do usuário . Seu script não deve assumir e ditar ao ambiente do usuário qual codificação de caracteres usar. Se o Python não pegar as configurações automaticamente,PYTHONIOENCODING
poderá ser definido para o seu script. Você não deve precisar disso, a menos que a saída seja redirecionada para um arquivo / canal.fazer o trabalho, mas não pode configurá-lo no próprio python ...
o que podemos fazer é verificar se não está definido e dizer ao usuário para defini-lo antes do script de chamada com:
Atualize para responder ao comentário: o problema existe apenas ao passar para o stdout. Eu testei no Fedora 25 Python 2.7.13
cat b.py
running ./b.py
executando ./b.py | Menos
fonte
sys.stdout.encoding
é definido automaticamente com base noLC_CTYPE
valor da localidade.Eu tive um problema semelhante na semana passada . Foi fácil de corrigir no meu IDE (PyCharm).
Aqui estava minha correção:
A partir da barra de menus do PyCharm: Arquivo -> Configurações ... -> Editor -> Codificações de arquivo e defina: "IDE Encoding", "Project Encoding" e "Project Encoding" e "Default codification for properties files" ALL para UTF-8 e agora ela funciona como um encanto.
Espero que isto ajude!
fonte
Uma versão higienizada discutível da resposta de Craig McQueen.
Uso:
fonte
Eu poderia "automatizá-lo" chamando:
Sim, é possível obter um loop infinito aqui se esse "setenv" falhar.
fonte
Eu apenas pensei em mencionar algo aqui que eu tive que passar muito tempo experimentando antes de finalmente perceber o que estava acontecendo. Isso pode ser tão óbvio para todos aqui que eles nem se deram ao trabalho de mencioná-lo. Mas teria me ajudado se eles tivessem, então, nesse princípio ...!
NB: Estou usando o Jython especificamente, v 2.7, portanto, possivelmente isso pode não se aplicar ao CPython ...
NB2: as duas primeiras linhas do meu arquivo .py aqui são:
O mecanismo de construção de cadeia "%" (AKA "interpolation operator") também causa problemas ADICIONAIS ... Se a codificação padrão do "ambiente" for ASCII e você tentar fazer algo como
Você não terá dificuldade em executar no Eclipse ... Em uma CLI do Windows (janela do DOS), você encontrará que a codificação é a página de código 850 (meu sistema operacional Windows 7) ou algo semelhante, que pode manipular pelo menos caracteres acentuados europeus, por isso vou trabalhar.
também irá funcionar.
Se, OTOH, você direcionar para um arquivo da CLI, a codificação stdout será None, que será padronizada como ASCII (no meu sistema operacional de qualquer maneira), que não poderá lidar com nenhuma das impressões acima ... (codificação temida erro).
Então, você pode pensar em redirecionar seu stdout usando
e tente executar na tubulação da CLI para um arquivo ... Muito estranhamente, a impressão A acima funcionará ... Mas a impressão B acima gerará o erro de codificação! No entanto, o seguinte funcionará bem:
A conclusão a que cheguei (provisoriamente) é que, se uma string especificada como Unicode usando o prefixo "u" for submetida ao mecanismo de% -handling, ela envolverá o uso da codificação de ambiente padrão, independentemente de se você configurou o stdout para redirecionar!
Como as pessoas lidam com isso é uma questão de escolha. Gostaria de receber um especialista em Unicode para dizer por que isso acontece, se de alguma forma eu entendi errado, qual a solução preferida para isso, se também se aplica ao CPython , se ocorre no Python 3, etc., etc.
fonte
"fréd"
é uma sequência de bytes e não uma sequência Unicode, portanto ocodecs.getwriter
wrapper o deixará em paz. Você precisa de uma liderançau
, oufrom __future__ import unicode_literals
.Encontrei esse problema em um aplicativo herdado e era difícil identificar onde estava o conteúdo impresso. Eu me ajudei com esse hack:
No topo do meu script, test.py:
Observe que isso altera TODAS as chamadas para impressão para usar uma codificação; portanto, seu console imprimirá o seguinte:
fonte
No Windows, tive esse problema com muita frequência ao executar um código Python a partir de um editor (como Sublime Text), mas não se o executasse na linha de comando.
Nesse caso, verifique os parâmetros do seu editor. No caso do SublimeText, isso
Python.sublime-build
resolveu:fonte