2014-09-19 3 views
0

Используя следующий код (в PHP) я посылаю строку в программу питона:Как декодировать аргументы python юникода?

shell_exec("python3 /var/www/html/app.py \"$text\""); 

$text переменная содержит неанглийскую строку. Проблема в том, когда я печатаю аргументы в Python с print(sys.argv) я получаю результат:

['/var/www/html/app.py', '\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab'] 

Как преобразовать эту строку в юникод исходной форме текста в питона?

+0

Какой выход вы ожидаете? Эти кодовые обозначения являются суррогатами. – geoffspear

+0

@Wooble Я хочу использовать этот текст в функции, которая работает с нормальными строками, а не с unicodes. – hpn

ответ

2

Python использует свой LOC ale для декодирования байтов, которые он получает из командной строки. По умолчанию C locale использует ascii. $text похоже в utf-8. Поэтому Python должен использовать обработчик ошибок surrogateescape, чтобы декодировать эти байты в текст sys.argv[1], который производит одиночные суррогаты, такие как '\udcd8', которые вы видите на выходе.

Вы можете использовать UTF-8 локали, например, LC_ALL=C.UTF-8 или перекодировать аргументы вручную: sys.argv[1].encode(locale.getpreferredencoding(True), 'surrogateescape').decode('utf-8'):

>>> s = u'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8\udcb4\udcda\udca9 \udcd8\udcae\udcd8\udcab\udcd9\udc87\udcd8\udca8 \udcd8\udcaa\udcd8\udcb4\udcd8\udcb5\udcd8\udcab' 
>>> print(s.encode('ascii', 'surrogateescape').decode('utf-8')) 
بتصشک خثهب تشصث 
+0

Я получаю эту ошибку при перекодировании аргументов вручную:' UnicodeEncodeError: 'ascii' кодек не может кодировать символы в позиции 0-5: порядковый номер не в диапазоне (128) ' – hpn

+0

@hpn: я добавил пример кода, нет ошибки – jfs

2
shell_exec("python3 /var/www/html/app.py \"$text\""); 

(я надеюсь, что $text сильно продезинфицировать, избегал, или статического! Если пользовательский ввод получил здесь у вас есть ужасная уязвимость удаленного выполнения кода!)

'\udcd8\udca8\udcd8\udcaa\udcd8\udcb5\udcd8... 

ОК, что произошел здесь заключается в том, что PHP передал строку с кодировкой UTF-8 на Python, но Python не знал, что ввод командной строки был UTF-8. (Часто, когда вы запускаете Python в качестве команды, он может работать с вашим терминалом, но нет терминала, когда он работает на PHP под управлением Python на веб-сервере.)

Не зная, какой вход был по умолчанию равным ASCII , Высокие байты на входе недействительны в ASCII, но Python 3 имеет обработчик «surrogateescape» для неверных байтов, который применяется к командной строке при декодировании его в строку Unicode. Это генерирует в противном случае недействительные суррогатные коды UTF-16 U + DC80-U + DCFF, но, по крайней мере, позволяет восстановить исходные высокие байты, если вы захотите.

Так как:

  • установить переменную PYTHONIOENCODING окружения UTF-8 перед выполнением Python, поэтому он знает, что правильно кодировка в первую очередь, или

  • изменить сценарий Python предварительного -Process свой вклад, чтобы восстановить правильный вход с sys.argv[1].encode('utf-8', 'surrogateescape').decode('utf-8')

+0

'PYTHONIOENCODING' не влияет на' sys.argv'. Вы должны использовать * ту же * кодировку символов для кодирования (не жестко кодировать '' utf-8''), поскольку Python использует для декодирования 'sys.argv'. – jfs

+0

@bobince +1 и спасибо за ваше предупреждение! установка PYTHONENCODING на utf-8 не работала, но 'LANG = en_US.utf-8' работает – hpn

Смежные вопросы