[Решено] Python CGI не обрабатывает формы, но в целом работает

Автор agentgoblin, 26 июня 2015, 06:49:54

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

agentgoblin

[ot]Заранее хочу попросить любителей фреймворков удалиться из темы.[/ot]

Проблема такая: есть Debian Jessie, Lighttpd 1.4.35 и Python3. В целом скрипты работают, hello world пишется и всё в порядке. Права у всех файлов нормальные, все скрипты под www-data и разрешением 755. Скриптом не обрабатываются формы, выводится пустая страница. При запуске этого же скрипта для обработки форм из консоли

python3 form.py TEXT_1=hello\&TEXT_2=world
выводится то, что нужно. При запуске тестового python-сервера командой "python3 -m http.server --cgi" и подключении на localhost:8000 скрипт так же прекрасно обрабатывает форму. Через lighttpd не работает.

Пытался добавить отладочный вывод через
import cgitb
cgitb.enable()

получаю пустую страницу без traceback, если пытаюсь писать в лог
import cgitb
cgitb.enable(display=0, logdir="/tmp")

то получаю на странице сообщение
A problem occurred in a Python script.

Tried to save traceback to /tmp/tmpt6hllcrt.html, but failed.

при этом файл  /tmp/tmpt6hllcrt.html создаётся, но он пустой.

Исходники проблемных страницы и скрипта


Код .html-страницы c формой:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Обработка данных форм</title>
</head>
<body>
    <form action="/web/cgi-bin/form.py">
        <input type="text" name="TEXT_1">
        <input type="text" name="TEXT_2">
        <input type="submit">
    </form>
</body>
</html>



Код скрипта на Python3:

#!/usr/bin/python3
import cgi
import html
import cgitb
cgitb.enable(display=0, logdir="/tmp")

form = cgi.FieldStorage()
text1 = form.getfirst("TEXT_1", "shit")
text2 = form.getfirst("TEXT_2", "shit")
text1 = html.escape(text1)
text2 = html.escape(text2)

print("Content-type: text/html\n")

print("<!DOCTYPE HTML> <html> <head> <meta charset=\"utf-8\"> <title>Обработка данных форм</title> </head> <body>")
print("<h1>Обработка данных форм!</h1>")

print("<p>TEXT_1: {}</p>".format(text1))
print("<p>TEXT_2: {}</p>".format(text2))

print("</body> </html>")

[свернуть]

Конфигурация cgi для lighttpd:
server.modules += ( "mod_cgi" )

$HTTP["url"] =~ "^/web/cgi-bin" {
        cgi.assign = ( ".py" => "/usr/bin/python3" )
}


Пример скрипта, который отлично работает и печатает что надо

#!/usr/bin/python3

print( "Content-Type: text/html\n\n" )
print( '<html><head><meta content="text/html; charset=UTF-8" />' )
print( '<title>Raspberry Pi</title><p>' )
for count in range(1,100):
  print( 'Hello&nbsp;World... ' )
print( "</p></body></html>" )
[свернуть]

ihammers

Фрейм, не фрейм, а попытаться стоит повысить уровень логирования в Lighttpd.
Обратите внимание на 5-тый пункт lightttpd-python.
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290

agentgoblin

#2
Огромное спасибо, добавил, как по ссылке, опцию в конфиг lighttpd
server.breakagelog = "/var/log/lighttpd/breakage.log"
и сразу нашёл проблему:
ЦитироватьTraceback (most recent call last):
  File "/var/www/web/cgi-bin/form.py", line 15, in <module>
    print("<!DOCTYPE HTML> <html> <head> <meta charset=\"utf-8\"> <title>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0444\u043e\u0440\u043c</title> </head> <body>")
UnicodeEncodeError: 'ascii' codec can't encode characters in position 60-68: ordinal not in range(128)

Суть ошибки описана тут:
Копипаста с ru.stackoverflow.com
ЦитироватьПитон использует кодировку терминала для печати, которая не имеет никакого отношения к sys.getdefaultencoding().

Иногда переменные окружения, определяющие язык, такие как LANGUAGE, LC_ALL,LC_CTYPE, LANG могут быть не установлены, например, в окружении используемом ssh, upstart, Salt, mod_wsgi, crontab, etc. В этом случае используется C (POSIX) локаль, которая использует ascii кодировку, что приводит к UnicodeEncodeError ошибке, т.к. русские буквы не представимы в ascii.

<...>

Ошибка в вопросе связана с Питон багом: Python 3 raises Unicode errors with the C locale (http://bugs.python.org/issue19846). Разработчики решили следовать ascii кодировке из C локали, даже если это ошибка в подавляющем большинстве случаев.

Чтобы временно изменить используемую кодировку можно определить PYTHONIOENCODING:

$ PYTHONIOENCODING=utf-8 python your-script.py

В качестве более постоянного решения, нужно убедится что используется utf-8 локаль в окружении, которое запускает python. Не обязательно русскую локаль устанавливать, чтобы напечатать русский текст. В этом достоинство Юникода, что можно работать с многими языками одновременно. Например, существует C.UTF-8 локаль.
[свернуть]

<drama deleted>

Cообщение объединено 26 июня 2015, 18:51:17

Победил. Кусок конфига /etc/lighttpd/lighttpd.conf:


server.modules += (
        "mod_setenv"
)

setenv.add-environment = ( "LANG" => env.LANG )


У кого системная локаль не UTF-8, вместо env.LANG так и укажите "UTF-8".

Всем спасибо за поддержку.