Ошибки при попытке сохранить вывод командной строки в файл

Я запускал инструмент python и пытался сохранить его вывод в файл. Если я не сохраняю вывод в файл, инструмент работает отлично. Но когда я пытаюсь сохранить вывод в файл, он выдает следующую ошибку и прерывает программу:

  File "./androdiff.py", line 118, in <module>
main(options, arguments)
  File "./androdiff.py", line 94, in main
ddm.show()
  File "./elsim/elsim/elsim_dalvik.py", line 772, in show
self.eld.show()
  File "./elsim/elsim/elsim.py", line 435, in show
i.show()
  File "./elsim/elsim/elsim_dalvik.py", line 688, in show
  print hex(self.bb.bb.start + self.offset), self.pos_instruction, self.ins.get_name(), self.ins.show_buff( self.bb.bb.start + self.offset )
  UnicodeEncodeError: 'ascii' codec can't encode character u'\u0111' in position 35: ordinal not in range(128)

Я пробовал command |less, command > output и command | tee output, все они будут вызывать такую ​​ошибку.

Пожалуйста, помогите решить проблему.

Спасибо!

Ответ 1

Вы должны указать кодировку своей строки перед ее печатью:

print unicode(hex(self.bb.bb.start + self.offset)).encode('utf-8')
print unicode(self.pos_instruction, self.ins.get_name()).encode('utf-8')
print unicode(self.ins.show_buff( self.bb.bb.start + self.offset )).encode('utf-8')

Причина этого в том, что python автоматически кодирует вашу строку правильно (в вашем случае utf-8) при печати на терминал (он обнаруживает, что терминал использует utf-8).

Если вы перенаправляете свой вывод в файл, Python не имеет информации о том, какую кодировку он должен использовать, и по умолчанию используется вместо ascii (что вызывает вашу ошибку).

Как правило, убедитесь, что вы всегда кодируете строку перед печатью, чтобы сделать print работать во всех средах.

Лучшим методом может быть определение вашего собственного метода печати для этого:

def myprint(unicodestr): 
    print unicodestr.encode('utf-8')

Если вы хотите избежать вышеуказанного и сделать печать с помощью кодировки utf-8 по умолчанию, вы можете сделать

import sys
import codecs
sys.stdout=codecs.getwriter('utf-8')(sys.stdout)

Остерегайтесь такого подхода! Некоторые сторонние библиотеки могут зависеть от кодировки по умолчанию ascii и break. Обратите внимание, что весь этот беспорядок был разрешен в Python 3 (по умолчанию используется кодировка UTF-8)

Ответ 2

Установить переменную среды PYTHONIOENCODING явно, если кодировка символов stdout не может быть определена автоматически, например, когда выход перенаправляется в файл:

$ PYTHONIOENCODING=utf-8 python app.py > file

Не кодируйте кодировку символов в своих сценариях, если вывод может перейти к терминалу; напечатайте строки Unicode и разрешите пользователям настраивать их среду.