Python: UnicodeEncodeError, когда я использую grep

Я использую простой скрипт на python для получения результатов бронирования для моего CID: simple.py:

data = {"minorRev":"current minorRev #","cid":"xxx","apiKey":"xxx","customerIpAddress":"  ","creationDateStart":"03/31/2013","}

url = 'http://someservice/services/rs/'                      
req = requests.get(url,params=data)                        
print req                                                                 
print req.text                                                                
print req.status_code

Теперь в командной строке, если я делаю python simple.py он отлично работает и печатает переменную req.text

Однако, когда я пытаюсь сделать

python simple.py | grep pattern

я получил

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 1314: ordinal not in range(128)

Ответ 1

print требуется для кодирования строки перед отправкой на stdout, но когда процесс находится в канале, значение sys.stdout.encoding равно None, поэтому print получает unicode, а затем он пытается кодировать этот объект с помощью кодека ascii - если в этом объекте unicode есть символы, отличные от ASCII, будет создано исключение.

Вы можете решить эту проблему, кодируя все объекты unicode, прежде чем отправлять ее на стандартный вывод (но вам нужно угадать, какой кодек использовать). См. Следующие примеры:

Файл wrong.py:

# coding: utf-8

print u'Álvaro'

Результат:

[email protected]:/tmp
$ python wrong.py 
Álvaro
[email protected]:/tmp
$ python wrong.py | grep a
Traceback (most recent call last):
  File "wrong.py", line 3, in <module>
    print u'Álvaro'
UnicodeEncodeError: 'ascii' codec can't encode character u'\xc1' in position 0: ordinal not in range(128)

Файл right.py:

# coding: utf-8

print u'Álvaro'.encode('utf-8')
# unicode object encoded == `str` in Python 2

Результат:

[email protected]:/tmp
$ python right.py 
Álvaro
[email protected]:/tmp
$ python right.py | grep a
Álvaro

Ответ 2

Если sys.stdout.isatty() является ложным (выход перенаправляется на файл/канал), то настройте PYTHONIOENCODING envvar вне вашего script. Всегда печатайте Unicode, не кодируйте кодировку символов своей среды внутри script:

$ PYTHONIOENCODING=utf-8 python simple.py | grep pattern