Primeiro: reload(sys)
configurar uma codificação padrão aleatória apenas para a necessidade de um fluxo de terminal de saída é uma prática recomendada.reload
geralmente muda as coisas no sys que foram implementadas dependendo do ambiente - por exemplo, sys.stdin / stdout streams, sys.excepthook, etc.
Resolvendo o problema de codificação no stdout
A melhor solução que eu conheço para resolver o problema de codificação de print
strings unicode e além de ascii str
(por exemplo, de literais) em sys.stdout é: cuidar de um sys.stdout (objeto semelhante a arquivo) que seja capaz e opcionalmente tolerante em relação às necessidades:
Quando sys.stdout.encoding
é None
por algum motivo, ou não-existente, ou erroneamente falsa ou "menos" do que o que o terminal stdout ou transmitir realmente é capaz de, em seguida, tentar fornecer uma correta .encoding
atributo. Por fim, substituindo sys.stdout & sys.stderr
por um objeto semelhante a arquivo de tradução.
Quando o terminal / fluxo ainda não pode codificar todos os caracteres unicode ocorrentes, e quando você não deseja interromper print
apenas por causa disso, é possível introduzir um comportamento de codificar com substituir no objeto de conversão de arquivo.
Aqui está um exemplo:
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
Usando literais de cadeia simples além do ascii no código Python 2/2 + 3
A única boa razão para alterar a codificação padrão global (apenas para UTF-8) é uma decisão sobre o código-fonte do aplicativo - e não por causa de problemas de codificação de fluxo de E / S: Para escrever literais de cadeia além do ascii no código sem ser forçado para sempre usar u'string'
escape unicode de estilo. Isso pode ser feito de maneira bastante consistente (apesar do que o artigo de anonbadger diz), cuidando de uma base de código-fonte Python 2 ou Python 2 + 3 que usa consistentemente literais de cadeia simples ascii ou UTF-8 - na medida em que essas cadeias potencialmente sofrem silêncio conversão unicode e mova-se entre módulos ou, potencialmente, vá para stdout. Para isso, prefira "# encoding: utf-8
"ou ascii (sem declaração). Altere ou descarte bibliotecas que ainda dependem de maneira muito idiota fatalmente de erros de codificação padrão ascii além da chr # 127 (que hoje é rara hoje).
E faça isso no início do aplicativo (e / ou no site sitecustomize.py), além do SmartStdout
esquema acima - sem usar reload(sys)
:
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
Dessa maneira, literais de string e a maioria das operações (exceto a iteração de caracteres) funcionam confortavelmente sem pensar na conversão unicode como se houvesse apenas Python3. É claro que as E / S de arquivos sempre precisam de cuidados especiais com relação às codificações - como no Python3.
Nota: as sequências de planícies são convertidas implicitamente de utf-8 em unicode SmartStdout
antes de serem convertidas no encconding do fluxo de saída.