0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В стандартной библиотеке Python есть встроенный WSGI-сервер -<a>wsgiref</a>. На практике чаще используются gunicorn, uWSGI и другие серверы, но функционала встроенного нам хватит для обучающих целей. В этом уроке мы научимся использовать его.</p>
1
<p>В стандартной библиотеке Python есть встроенный WSGI-сервер -<a>wsgiref</a>. На практике чаще используются gunicorn, uWSGI и другие серверы, но функционала встроенного нам хватит для обучающих целей. В этом уроке мы научимся использовать его.</p>
2
<h2>Запуск WSGI-сервера</h2>
2
<h2>Запуск WSGI-сервера</h2>
3
<p>Создадим модуль<em>example.py</em>. Это минимальное веб-приложение, которое будет возвращать текущее время:</p>
3
<p>Создадим модуль<em>example.py</em>. Это минимальное веб-приложение, которое будет возвращать текущее время:</p>
4
<p>Теперь создадим веб-сервер в модуле<em>server.py</em>. Импортируем из библиотеки wsgiref функцию make_server(). Она принимает параметрами адрес хоста, порт и приложение. Если хост указан как '', то будет использован localhost. Также функция возвращает экземпляр сервера.</p>
4
<p>Теперь создадим веб-сервер в модуле<em>server.py</em>. Импортируем из библиотеки wsgiref функцию make_server(). Она принимает параметрами адрес хоста, порт и приложение. Если хост указан как '', то будет использован localhost. Также функция возвращает экземпляр сервера.</p>
5
<p>Дальше нам нужно вызвать метод .serve_forever(), чтобы сервер постоянно обслуживал запросы, пока мы принудительно не завершим его процесс:</p>
5
<p>Дальше нам нужно вызвать метод .serve_forever(), чтобы сервер постоянно обслуживал запросы, пока мы принудительно не завершим его процесс:</p>
6
<p>Запустим веб-сервер:</p>
6
<p>Запустим веб-сервер:</p>
7
<p>Когда сервер будет запущен, он полностью забирает управление. Вкладка терминала больше не доступна для ввода команд. В отличие от обычных скриптов, которые выполняют свою задачу и заканчиваются, веб-сервера должны слушать порт непрерывно и сразу реагировать на входящие соединения. Поэтому сервер продолжит работать, пока его не остановят.</p>
7
<p>Когда сервер будет запущен, он полностью забирает управление. Вкладка терминала больше не доступна для ввода команд. В отличие от обычных скриптов, которые выполняют свою задачу и заканчиваются, веб-сервера должны слушать порт непрерывно и сразу реагировать на входящие соединения. Поэтому сервер продолжит работать, пока его не остановят.</p>
8
<p>Остановить сервер можно с помощью команды: Ctrl-C.</p>
8
<p>Остановить сервер можно с помощью команды: Ctrl-C.</p>
9
<p>Такой способ запуска удобен в разработке, но в реальном окружении сервера запускают в виде демонов. Демон - процесс операционной системы, работающий в фоне.</p>
9
<p>Такой способ запуска удобен в разработке, но в реальном окружении сервера запускают в виде демонов. Демон - процесс операционной системы, работающий в фоне.</p>
10
<p>Если в это время попытаться запустить еще один веб-сервер в соседней вкладке на том же порту, то запуск завершится с такой ошибкой:</p>
10
<p>Если в это время попытаться запустить еще один веб-сервер в соседней вкладке на том же порту, то запуск завершится с такой ошибкой:</p>
11
<blockquote><p>OSError: [Errno 98] Address already in use</p>
11
<blockquote><p>OSError: [Errno 98] Address already in use</p>
12
</blockquote><p>Такая ошибка означает, что какой-то процесс занял соответствующий порт - в данном случае 8000. В такой ситуации нужно либо остановить процесс, который мешает, либо стартовать на другом порту.</p>
12
</blockquote><p>Такая ошибка означает, что какой-то процесс занял соответствующий порт - в данном случае 8000. В такой ситуации нужно либо остановить процесс, который мешает, либо стартовать на другом порту.</p>
13
<p>Посмотреть, какой процесс занял порт 8000, можно командой ss -ltnup 'sport = :8000'.</p>
13
<p>Посмотреть, какой процесс занял порт 8000, можно командой ss -ltnup 'sport = :8000'.</p>
14
<p>После этого нужно открыть браузер и ввести http://localhost:8000. На экран выведется текущее время. В терминале, где запущен веб-сервер, появятся записи, которые показывают входящие запросы:</p>
14
<p>После этого нужно открыть браузер и ввести http://localhost:8000. На экран выведется текущее время. В терминале, где запущен веб-сервер, появятся записи, которые показывают входящие запросы:</p>
15
<p>Теперь снова откроем файл<em>example.py</em>и изменим строчку, чтобы выводить еще и сегодняшний месяц и день - data = bytes(f'The time is {time:%b %d %H:%M:%S}', 'utf-8'). Выполните f5 в браузере, и вы увидите, что изменения не применились.</p>
15
<p>Теперь снова откроем файл<em>example.py</em>и изменим строчку, чтобы выводить еще и сегодняшний месяц и день - data = bytes(f'The time is {time:%b %d %H:%M:%S}', 'utf-8'). Выполните f5 в браузере, и вы увидите, что изменения не применились.</p>
16
<p>Сервер загружает модуль единожды и на каждый запрос запускает переданную в него функцию. Чтобы применились изменения, нужно перезапустить сервер. Со многими веб-фреймворками поставляется development-сервер, который работает в режиме auto-reload, то есть перезагружается при каждом изменении кода. Но в production режиме нужно перезагружать вручную.</p>
16
<p>Сервер загружает модуль единожды и на каждый запрос запускает переданную в него функцию. Чтобы применились изменения, нужно перезапустить сервер. Со многими веб-фреймворками поставляется development-сервер, который работает в режиме auto-reload, то есть перезагружается при каждом изменении кода. Но в production режиме нужно перезагружать вручную.</p>