система php, python и utf-8

У меня есть программа на Python, которая работает очень хорошо. Он подключается к нескольким веб-сайтам и выводит нужную информацию. Поскольку не все веб-сайты закодированы с помощью utf-8, я запрашиваю кодировку из заголовков и использую метод unicode(string, encoding) для декодирования (я не уверен, что это подходящий способ сделать это, но он работает довольно хорошо). Когда я запускаю программу python, я не получаю ??? маркирует и работает нормально. Но когда я запускаю программу с помощью функции system php, я получаю эту ошибку:

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

Это специфичная для Python ошибка, но меня смущает то, что я не получаю эту ошибку, когда запускаю программу с помощью терминала. Я получаю это только тогда, когда использую функцию system php и вызываю программу из php. Что может быть причиной этой проблемы?

Вот пример кода:

php-код, который вызывает программу python:

system("python somefile.py $search") // where $search is the variable coming from an input

код питона:

encoding = "iso-8859-9"
l = "some string here with latin characters"
print unicode("<div class='line'>%s</div>" % l, encoding)
# when I run this code from terminal it works perfect and I receive no ??? marks
# when I run this code from php, I receive the error above

person Shaokan    schedule 09.09.2011    source источник
comment
Вероятно, это переменная среды.   -  person Chris Eberle    schedule 09.09.2011


Ответы (2)


Из вики PrintFails:

Когда Python обнаруживает, что его выходные данные подключены к терминалу, он устанавливает атрибут sys.stdout.encoding в кодировку терминала. Обработчик оператора print автоматически кодирует аргументы Unicode в вывод str.

Вот почему ваша программа работает при вызове из терминала.

Когда Python не определяет желаемый набор символов вывода, он устанавливает для sys.stdout.encoding значение None, и печать вызывает кодек «ascii».

Вот почему ваша программа не работает при вызове из php. Чтобы заставить его работать при вызове из php, вам нужно явно указать, какую кодировку print следует использовать. Например, чтобы явно указать, что вы хотите, чтобы вывод был закодирован в utf-8 (если он не подключен к терминалу):

ENCODING = sys.stdout.encoding if sys.stdout.encoding else 'utf-8'
print unicode("<div class='line'>%s</div>" % l, encoding).encode(ENCODING)

Кроме того, вы можете установить переменную среды PYTHONIOENCODING. Тогда ваш код должен работать без изменений (как из терминала, так и при вызове из php).

person unutbu    schedule 09.09.2011

Когда вы запускаете скрипт python в своем терминале, ваш терминал, скорее всего, будет закодирован в UTF8 (особенно, если вы используете Linux или Mac).

Когда вы устанавливаете переменную l в "some string with latin characters", эта строка будет закодирована в кодировку по умолчанию, если вы используете терминал, l будет UTF8, и скрипт не сработает.

Небольшой совет: если у вас есть строка, закодированная в latin1, и вы хотите, чтобы она была в юникоде, вы можете сделать:

variable.decode('latin1')

person Diego Navarro    schedule 09.09.2011