Документация Python неофициальный перевод

asynchat.md

133 строк · 14.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.11/library/asynchat.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`asynchat`](https://python-all.ru/3.11/library/asynchat.html#module-asynchat) – Асинхронный обработчик команд/ответов через сокеты89**Исходный код:** [Lib/asynchat.py](https://python-all.ru/src/3.11/Lib/asynchat.py)1011Устарело с версии 3.6, будет удалено в версии 3.12: Модуль [`asynchat`](https://python-all.ru/3.11/library/asynchat.html#module-asynchat) устарел (см. [**PEP 594**](https://python-all.ru/3.11/library/asynchat.html) подробнее). Вместо него используйте [`asyncio`](https://python-all.ru/3.11/library/asyncio.html#module-asyncio).1213---1415> **Примечание**16>17> Этот модуль существует только для обратной совместимости. Для нового кода рекомендуется использовать [`asyncio`](https://python-all.ru/3.11/library/asyncio.html#module-asyncio).1819Этот модуль построен на основе инфраструктуры [`asyncore`](https://python-all.ru/3.11/library/asyncore.html#module-asyncore), упрощая реализацию асинхронных клиентов и серверов, а также обработку протоколов, элементы которых завершаются произвольными строками или имеют переменную длину. [`asynchat`](https://python-all.ru/3.11/library/asynchat.html#module-asynchat) определяет абстрактный класс [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat), который нужно наследовать, реализуя методы `collect_incoming_data()` и `found_terminator()`. Он использует тот же асинхронный цикл, что и [`asyncore`](https://python-all.ru/3.11/library/asyncore.html#module-asyncore), и два типа каналов – [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher) и [`asynchat.async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) – могут свободно сочетаться в карте каналов. Обычно серверный канал [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher) создаёт новые объекты канала [`asynchat.async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) при получении входящих запросов на соединение.2021[Доступность](https://python-all.ru/3.11/library/intro.html#availability): not Emscripten, not WASI.2223Этот модуль не работает или недоступен на платформах WebAssembly `wasm32-emscripten` и `wasm32-wasi`. См. [платформы WebAssembly](https://python-all.ru/3.11/library/intro.html#wasm-availability) для получения дополнительной информации.2425#### `class asynchat.async_chat`2627Этот класс является абстрактным подклассом [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher). Чтобы использовать его на практике, необходимо наследовать [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat), реализовав осмысленные методы [`collect_incoming_data()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.collect_incoming_data) и [`found_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.found_terminator). Методы [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher) можно использовать, хотя не все из них имеют смысл в контексте сообщений/ответов.2829Как и [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher), [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) определяет набор событий, порождаемых анализом состояния сокета после вызова `select()`. Как только цикл опроса запущен, методы объекта [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) вызываются каркасом обработки событий без каких-либо действий со стороны программиста.3031Два атрибута класса можно изменять для повышения производительности или, возможно, даже для экономии памяти.3233#### `ac_in_buffer_size`3435Размер асинхронного входного буфера (по умолчанию `4096`).3637#### `ac_out_buffer_size`3839Размер асинхронного выходного буфера (по умолчанию `4096`).4041В отличие от [`asyncore.dispatcher`](https://python-all.ru/3.11/library/asyncore.html#asyncore.dispatcher), [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) позволяет определить очередь FIFO из *производителей*. Производителю нужен всего один метод `more()`, который должен возвращать данные для передачи по каналу. Производитель сигнализирует об исчерпании данных (*т.е.* что у него больше нет данных), возвращая из метода `more()` пустой объект bytes. В этот момент объект [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat) удаляет производителя из очереди и начинает использовать следующего, если он есть. Когда очередь производителей пуста, метод `handle_write()` ничего не делает. Используйте метод канала [`set_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.set_terminator), чтобы задать способ распознавания конца или важной точки останова во входящей передаче от удалённой стороны.4243Чтобы создать работоспособный подкласс [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat), ваши входные методы [`collect_incoming_data()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.collect_incoming_data) и [`found_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.found_terminator) должны обрабатывать данные, которые канал получает асинхронно. Методы описаны ниже.4445#### `async_chat.close_when_done()`4647Помещает `None` в очередь производителей. Когда этот производитель извлекается из очереди, он вызывает закрытие канала.4849#### `async_chat.collect_incoming_data(data)`5051Вызывается с параметром *data*, содержащим произвольный объём полученных данных. Метод по умолчанию (должен быть переопределён) возбуждает исключение [`NotImplementedError`](https://python-all.ru/3.11/library/exceptions.html#NotImplementedError).5253#### `async_chat.discard_buffers()`5455В аварийных ситуациях этот метод сбрасывает все данные, находящиеся во входном и/или выходном буферах, а также в очереди производителей.5657#### `async_chat.found_terminator()`5859Вызывается, когда входящий поток данных соответствует условию завершения, заданному [`set_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.set_terminator). Метод по умолчанию (должен быть переопределён) возбуждает исключение [`NotImplementedError`](https://python-all.ru/3.11/library/exceptions.html#NotImplementedError). Буферизованные входные данные должны быть доступны через атрибут экземпляра.6061#### `async_chat.get_terminator()`6263Возвращает текущий терминатор канала.6465#### `async_chat.push(data)`6667Помещает данные в очередь канала для гарантированной передачи. Это всё, что нужно сделать, чтобы канал записал данные в сеть, хотя в более сложных схемах можно использовать собственных производителей, например, для шифрования или разбиения на блоки.6869#### `async_chat.push_with_producer(producer)`7071Принимает объект-производитель и добавляет его в очередь производителей, связанную с каналом. Когда все ранее помещённые в очередь производители будут исчерпаны, канал начнёт потреблять данные этого производителя, вызывая его метод `more()`, и отправлять данные удалённой стороне.7273#### `async_chat.set_terminator(term)`7475Устанавливает условие завершения, которое будет распознаваться на канале. `term` может быть одним из трёх типов значений, соответствующих трём различным способам обработки входящих протокольных данных.7677| term | Описание |78| --- | --- |79| *строка* | Вызовет [`found_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.found_terminator), когда строка будет найдена во входном потоке данных |80| *целое* | Вызовет [`found_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.found_terminator), когда будет получено указанное количество символов |81| `None` | Канал продолжает собирать данные бесконечно |8283Обратите внимание, что любые данные после терминатора будут доступны для чтения каналом после вызова [`found_terminator()`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat.found_terminator).8485## Пример asynchat8687Следующий неполный пример показывает, как HTTP-запросы можно читать с помощью [`async_chat`](https://python-all.ru/3.11/library/asynchat.html#asynchat.async_chat). Веб-сервер может создавать объект `http_request_handler` для каждого входящего подключения клиента. Обратите внимание, что изначально терминатор канала устанавливается на пустую строку в конце HTTP-заголовков, а флаг указывает, что заголовки читаются.8889После чтения заголовков, если запрос имеет тип POST (что указывает на наличие дополнительных данных во входном потоке), то заголовок `Content-Length:` используется для установки числового терминатора для чтения нужного количества данных из канала.9091Метод `handle_request()` вызывается после того, как все соответствующие входные данные были маршализированы, после установки терминатора канала на `None`, чтобы любые посторонние данные, отправленные веб-клиентом, игнорировались.9293```python94import asynchat9596class http_request_handler(asynchat.async_chat):9798    def __init__(self, sock, addr, sessions, log):99        asynchat.async_chat.__init__(self, sock=sock)100        self.addr = addr101        self.sessions = sessions102        self.ibuffer = []103        self.obuffer = b""104        self.set_terminator(b"\r\n\r\n")105        self.reading_headers = True106        self.handling = False107        self.cgi_data = None108        self.log = log109110    def collect_incoming_data(self, data):111        """Буферизировать данные"""112        self.ibuffer.append(data)113114    def found_terminator(self):115        if self.reading_headers:116            self.reading_headers = False117            self.parse_headers(b"".join(self.ibuffer))118            self.ibuffer = []119            if self.op.upper() == b"POST":120                clen = self.headers.getheader("content-length")121                self.set_terminator(int(clen))122            else:123                self.handling = True124                self.set_terminator(None)125                self.handle_request()126        elif not self.handling:127            self.set_terminator(None)  # браузеры иногда отправляют лишние данные128            self.cgi_data = parse(self.headers, b"".join(self.ibuffer))129            self.handling = True130            self.ibuffer = []131            self.handle_request()132```133