← Назад к вопросам
Что делать, если нет веб-фреймворков?
2.4 Senior🔥 141 комментариев
#DevOps и инфраструктура#Django
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разработка веб-приложений без фреймворков
Это отличный вопрос, который проверяет глубину понимания того, как работают веб-приложения. Даже без фреймворков, Python предоставляет встроенные инструменты для создания веб-серверов.
Почему это может быть нужно
- Образовательные цели (понимание основ HTTP, WSGI)
- Специфические требования (минимальные зависимости)
- Встроенные системы с ограничениями
- Критичная производительность и контроль
Вариант 1: http.server (встроенный модуль)
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
from urllib.parse import urlparse, parse_qs
class SimpleAPIHandler(BaseHTTPRequestHandler):
"""Простой обработчик HTTP запросов"""
def do_GET(self):
"""Обработка GET запросов"""
path = urlparse(self.path).path
if path == "/":
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {"message": "Welcome to simple API"}
self.wfile.write(json.dumps(response).encode())
elif path.startswith("/users/"):
user_id = path.split("/")[-1]
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {"id": user_id, "name": "John", "email": "john@example.com"}
self.wfile.write(json.dumps(response).encode())
else:
self.send_response(404)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {"error": "Not found"}
self.wfile.write(json.dumps(response).encode())
def do_POST(self):
"""Обработка POST запросов"""
content_length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(content_length)
try:
data = json.loads(body.decode())
self.send_response(201)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {"message": "Created", "data": data}
self.wfile.write(json.dumps(response).encode())
except json.JSONDecodeError:
self.send_response(400)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {"error": "Invalid JSON"}
self.wfile.write(json.dumps(response).encode())
def log_message(self, format, *args):
"""Подавить логирование по умолчанию"""
pass
if __name__ == "__main__":
server = HTTPServer(("localhost", 8000), SimpleAPIHandler)
print("Server running on http://localhost:8000")
server.serve_forever()
Запуск:
python simple_server.py
curl http://localhost:8000/
curl http://localhost:8000/users/1
Плюсы:
- Нет зависимостей
- Встроено в Python
- Хорошо для образования
Минусы:
- Однопоточный (обработка одного запроса за раз)
- Не асинхронный
- Нужно писать много кода для простых вещей
Вариант 2: socketserver с многопоточностью
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
import json
import threading
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""HTTP сервер с поддержкой многопоточности"""
daemon_threads = True # Потоки завершаются с основной программой
class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# Каждый запрос обрабатывается в отдельном потоке
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
response = {
"message": "Hello from thread",
"thread": threading.current_thread().name
}
self.wfile.write(json.dumps(response).encode())
if __name__ == "__main__":
server = ThreadedHTTPServer(("localhost", 8000), RequestHandler)
print("Threaded server running")
server.serve_forever()
Вариант 3: WSGI (Web Server Gateway Interface)
Применим стандарт WSGI, который используется всеми фреймворками:
from wsgiref.simple_server import make_server
import json
from urllib.parse import urlparse
def application(environ, start_response):
"""WSGI приложение"""
path = environ.get("PATH_INFO", "/")
method = environ.get("REQUEST_METHOD", "GET")
if path == "/" and method == "GET":
response_body = json.dumps({"message": "Welcome"})
status = "200 OK"
headers = [("Content-Type", "application/json")]
elif path.startswith("/users/") and method == "GET":
user_id = path.split("/")[-1]
response_body = json.dumps({"id": user_id, "name": "John"})
status = "200 OK"
headers = [("Content-Type", "application/json")]
else:
response_body = json.dumps({"error": "Not found"})
status = "404 Not Found"
headers = [("Content-Type", "application/json")]
# Отправить ответ
start_response(status, headers)
return [response_body.encode()]
if __name__ == "__main__":
# WSGI сервер
httpd = make_server("localhost", 8000, application)
print("WSGI server running")
httpd.serve_forever()
Плюсы WSGI:
- Стандарт, поддерживаемый всеми серверами
- Разделение приложения и сервера
- Работает с gunicorn, uwsgi и др.
Вариант 4: Асинхронный сервер с asyncio
import asyncio
import json
from urllib.parse import urlparse
class SimpleAsyncServer:
def __init__(self, host="localhost", port=8000):
self.host = host
self.port = port
async def handle_client(self, reader, writer):
"""Обработать один клиента"""
try:
# Прочитать запрос
request_line = await reader.readuntil(b"\r\n")
request = request_line.decode().strip()
# Парсинг запроса
parts = request.split(" ")
method = parts[0]
path = parts[1]
# Пропустить остальные заголовки
while True:
line = await reader.readuntil(b"\r\n")
if line == b"\r\n":
break
# Формировать ответ
if path == "/":
response_body = json.dumps({"message": "Async API"})
status = "200 OK"
else:
response_body = json.dumps({"error": "Not found"})
status = "404 Not Found"
# Отправить HTTP ответ
response = (
f"HTTP/1.1 {status}\r\n"
f"Content-Type: application/json\r\n"
f"Content-Length: {len(response_body)}\r\n"
f"\r\n"
f"{response_body}"
)
writer.write(response.encode())
await writer.drain()
finally:
writer.close()
await writer.wait_closed()
async def start(self):
"""Запустить сервер"""
server = await asyncio.start_server(
self.handle_client,
self.host,
self.port
)
print(f"Async server running on {self.host}:{self.port}")
async with server:
await server.serve_forever()
if __name__ == "__main__":
server = SimpleAsyncServer()
asyncio.run(server.start())
Сравнение подходов
| Подход | Простота | Производительность | Асинхронность | Когда использовать |
|---|---|---|---|---|
| http.server | ⭐⭐⭐⭐⭐ | ⭐ | ❌ | Обучение, прототипы |
| ThreadingMixIn | ⭐⭐⭐⭐ | ⭐⭐ | ❌ | Простые приложения |
| WSGI | ⭐⭐⭐⭐ | ⭐⭐⭐ | ❌ | Production apps |
| asyncio | ⭐⭐⭐ | ⭐⭐⭐⭐ | ✅ | High-load API |
Реальный сценарий
В интервью я бы сказал:
"Если нет веб-фреймворков, я использую встроенные модули Python:
- Для прототипирования —
http.serverсо встроенным модулем - Для простого веб-приложения —
wsgirefс WSGI стандартом - Для production — я бы всё равно установил фреймворк (Flask, FastAPI, Django), потому что они предоставляют:
- Правильное разделение логики
- Встроенные утилиты (роутинг, валидация)
- Оптимизированную производительность
- Экосистему плагинов
Но понимание основ HTTP, WSGI и асинхронного программирования — это критично для качественного разработчика."