Python unicode popen или ошибка Popen при чтении unicode

У меня есть программа, которая генерирует следующий вывод:

             ┌───────────────────────┐
             │10 day weather forecast│
             └───────────────────────┘
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
Tonight Sep 27      Clear               54      0 %
Tue Sep 28          Sunny               85/61   0 %
Wed Sep 29          Sunny               86/62   0 %
Thu Sep 30          Sunny               87/65   0 %
Fri Oct 01          Sunny               85/62   0 %
Sat Oct 02          Sunny               81/59   0 %
Sun Oct 03          Sunny               79/56   0 %
Mon Oct 04          Sunny               78/58   0 %
Tue Oct 05          Sunny               81/61   0 %
Wed Oct 06          Sunny               81/61   0 %

Last Updated Sep 27 10:20 p.m. CT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

Кажется, это неправильно форматирует на этом сайте, но нижние строки вверху и верхние строки внизу приводят к ошибке юникода.

Вот пример кода для os.popen

>>> buffer = popen('10day', 'r').read()
Traceback (most recent call last):
  File "/home/woodnt/python/10_day_forecast.py", line 129, in <module>
    line_lower(51)
  File "/home/woodnt/python/lib/box.py", line 24, in line_lower
    print upper_line * len
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-50: ordinal not in range(128)
>>> print buffer

             ┌───────────────────────┐
             │10 day weather forecast│
             └───────────────────────┘

>>> 

Вот то же самое для subprocess.Popen:

f = Popen('10day', stdout=PIPE, stdin=PIPE, stderr=PIPE)
o, er = f.communicate()
print o

             ┌───────────────────────┐
             │10 day weather forecast│
             └───────────────────────┘

print er
Traceback (most recent call last):
  File "/home/woodnt/python/10_day_forecast.py", line 129, in <module>
    line_lower(51)
  File "/home/woodnt/python/lib/box.py", line 24, in line_lower
    print upper_line * len
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-50: ordinal not in range(128)

Любые идеи, если это можно заставить работать без большой работы «под капотом»? Я только изучаю программирование и начинаю с python


person narnie    schedule 28.09.2010    source источник
comment
Не знаю, почему форматирование так выключено выше. Мои извинения.   -  person narnie    schedule 28.09.2010


Ответы (1)


Я бы сказал, что запуск вашей программы из консоли должен работать правильно, потому что Python может угадать консольную кодировку окна терминала (cp437 в Windows для США), но при запуске через конвейер Python использует значение по умолчанию ascii. Попробуйте изменить свою программу на encode весь вывод Unicode на явную кодировку, например:

печать (upper_line * len).encode('cp437')

Затем, когда вы читаете его из канала, вы можете либо decode вернуться к Unicode, либо распечатать его прямо на терминале.

person Mark Tolonen    schedule 28.09.2010
comment
К сожалению, он отказывается от консоли. С консоли Python, как только вы выполните команду popen. Я думаю, вы правильно поняли, что канал по умолчанию использует ascii. Думаю, нет никакого способа изменить это поведение. Очень жаль. Это хорошая идея сделать, как вы предлагаете. Я попробую. - person narnie; 28.09.2010
comment
Вот так и получилось. Спасибо за отличную идею для работы. Я думаю, если бы это была другая программа, и у меня не было исходного кода, и это был бы двоичный файл, не было бы никакого способа обойти это, а? - person narnie; 28.09.2010
comment
Если исходной программой является Python, вы можете использовать os.environ['PYTHONIOENCODING'] = 'utf-8' перед Popen. Эта переменная среды указывает python использовать UTF-8 по умолчанию вместо ASCII. Все символы Unicode могут быть отправлены с помощью этой кодировки... просто .decode('utf-8') полученный результат возвращается обратно в Unicode. - person Mark Tolonen; 29.09.2010