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

asyncio-stream.md

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

1> **Источник:** https://python-all.ru/3.4/library/asyncio-stream.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.5.5. Потоки данных (API на основе корутин)89## 18.5.5.1. Функции потоков данных1011> **Примечание**12>13> Функции верхнего уровня в этом модуле представляют собой просто удобные обёртки; в них нет ничего особенного, и если они делают не в точности то, что нужно, можно свободно скопировать их код.1415#### `coroutine asyncio.open_connection(host=None, port=None, *, loop=None, limit=None, **kwds)`1617Обёртка для [`create_connection()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_connection), возвращающая пару (reader, writer).1819Возвращаемый reader – это экземпляр [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader), а writer – экземпляр [`StreamWriter`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter).2021Аргументы – это все обычные аргументы [`BaseEventLoop.create_connection()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_connection), кроме *protocol\_factory*; наиболее распространены позиционные host и port, за которыми следуют различные необязательные ключевые аргументы.2223Дополнительные необязательные ключевые аргументы: *loop* (для указания используемого экземпляра цикла событий) и *limit* (для задания лимита буфера, передаваемого в [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader)).2425Эта функция – [*корутина*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).2627#### `coroutine asyncio.start_server(client_connected_cb, host=None, port=None, *, loop=None, limit=None, **kwds)`2829Запускает сокетный сервер с колбэком для каждого подключившегося клиента. Возвращаемое значение такое же, как у [`create_server()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_server).3031Параметр *client\_connected\_cb* вызывается с двумя параметрами: *client\_reader* и *client\_writer*. *client\_reader* – это объект [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader), а *client\_writer* – объект [`StreamWriter`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter). Параметр *client\_connected\_cb* может быть либо обычной функцией колбэка, либо [*корутинной функцией*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine); если это корутинная функция, она будет автоматически преобразована в [`задачу`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.Task).3233Остальные аргументы – это все обычные аргументы [`create_server()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_server), кроме *protocol\_factory*; наиболее распространены позиционные *host* и *port*, за которыми следуют различные необязательные ключевые аргументы.3435Дополнительные необязательные ключевые аргументы: *loop* (для указания используемого экземпляра цикла событий) и *limit* (для задания лимита буфера, передаваемого в [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader)).3637Эта функция – [*корутина*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).3839#### `coroutine asyncio.open_unix_connection(path=None, *, loop=None, limit=None, **kwds)`4041Обёртка для [`create_unix_connection()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_unix_connection), возвращающая пару (reader, writer).4243См. [`open_connection()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.open_connection) для получения информации о возвращаемом значении и других деталях.4445Эта функция – [*корутина*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).4647Доступность: UNIX.4849#### `coroutine asyncio.start_unix_server(client_connected_cb, path=None, *, loop=None, limit=None, **kwds)`5051Запускает сервер UNIX Domain Socket с колбэком для каждого подключившегося клиента.5253См. [`start_server()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.start_server) для получения информации о возвращаемом значении и других деталях.5455Эта функция – [*корутина*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).5657Доступность: UNIX.5859## 18.5.5.2. StreamReader6061#### `class asyncio.StreamReader(limit=None, loop=None)`6263This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).6465#### `exception()`6667Получить исключение.6869#### `feed_eof()`7071Подтверждает конец файла (EOF).7273#### `feed_data(data)`7475Подаёт байты *data* во внутренний буфер. Любые операции, ожидающие данные, будут возобновлены.7677#### `set_exception(exc)`7879Устанавливает исключение.8081#### `set_transport(transport)`8283Устанавливает транспорт.8485#### `coroutine read(n=-1)`8687Читает до *n* байт. Если *n* не указан или равен `-1`, читает до EOF и возвращает все прочитанные байты.8889Если получен EOF и внутренний буфер пуст, возвращает пустой объект `bytes`.9091Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).9293#### `coroutine readline()`9495Читает одну строку, где «строка» – это последовательность байтов, заканчивающаяся `\n`.9697Если получен EOF, а `\n` не найден, метод вернёт частично прочитанные байты.9899Если получен EOF и внутренний буфер пуст, возвращает пустой объект `bytes`.100101Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).102103#### `coroutine readexactly(n)`104105Читает ровно *n* байт. Вызывает исключение [`IncompleteReadError`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.IncompleteReadError), если конец потока достигнут до того, как прочитано *n* байт; атрибут [`IncompleteReadError.partial`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.IncompleteReadError.partial) этого исключения содержит частично прочитанные байты.106107Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).108109#### `at_eof()`110111Возвращает `True`, если буфер пуст и был вызван метод [`feed_eof()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader.feed_eof).112113## 18.5.5.3. StreamWriter114115#### `class asyncio.StreamWriter(transport, protocol, reader, loop)`116117Оборачивает Transport.118119This exposes [`write()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.write), [`writelines()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.writelines), [`can_write_eof()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.can_write_eof), [`write_eof()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.write_eof), [`get_extra_info()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.get_extra_info) and [`close()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.close). It adds [`drain()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.drain) which returns an optional [`Future`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.Future) on which you can wait for flow control. It also adds a transport attribute which references the `Transport` directly.120121This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).122123#### `transport`124125Транспорт.126127#### `can_write_eof()`128129Возвращает [`True`](https://python-all.ru/3.4/library/constants.html#True), если транспорт поддерживает [`write_eof()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.write_eof), и [`False`](https://python-all.ru/3.4/library/constants.html#False) в противном случае. См. [`WriteTransport.can_write_eof()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.WriteTransport.can_write_eof).130131#### `close()`132133Закрывает транспорт: см. [`BaseTransport.close()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.BaseTransport.close).134135#### `coroutine drain()`136137Даёт возможность сбросить буфер записи нижележащего транспорта.138139Предполагаемое использование – записать:140141```python142w.write(data)143yield from w.drain()144```145146Когда размер буфера транспорта достигает верхнего порога (протокол приостанавливается), блокируется до тех пор, пока размер буфера не уменьшится до нижнего порога и протокол не будет возобновлён. Когда ждать нечего, yield-from продолжается немедленно.147148Использование [`drain()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.drain) с yield from даёт циклу событий возможность запланировать операцию записи и сбросить буфер. Особенно рекомендуется использовать этот метод, когда в транспорт записывается потенциально большой объём данных и корутина не использует yield from между вызовами [`write()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamWriter.write).149150Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).151152#### `get_extra_info(name, default=None)`153154Возвращает дополнительную информацию о транспорте: см. [`BaseTransport.get_extra_info()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.BaseTransport.get_extra_info).155156#### `write(data)`157158Записывает *данные* байт в транспорт: см. [`WriteTransport.write()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.WriteTransport.write).159160#### `writelines(data)`161162Записывает список (или любой итерируемый объект) байт данных в транспорт: см. [`WriteTransport.writelines()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.WriteTransport.writelines).163164#### `write_eof()`165166Закрывает записывающий конец транспорта после сброса буферизованных данных: см. [`WriteTransport.write_eof()`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.WriteTransport.write_eof).167168## 18.5.5.4. StreamReaderProtocol169170#### `class asyncio.StreamReaderProtocol(stream_reader, client_connected_cb=None, loop=None)`171172Вспомогательный класс для адаптации между протоколом [`Protocol`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.Protocol) и [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader). Подкласс протокола [`Protocol`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.Protocol).173174*потоковый\_читатель* – это экземпляр [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader), *колбэк\_подключения\_клиента* – необязательная функция, вызываемая с аргументами (stream\_reader, stream\_writer) при установке соединения, *цикл\_событий* – экземпляр цикла событий, который следует использовать.175176Это вспомогательный класс, а не превращение самого [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader) в подкласс протокола [`Protocol`](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio.Protocol), поскольку [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader) имеет другие возможные применения, а также чтобы пользователь [`StreamReader`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.StreamReader) случайно не вызывал неподходящие методы протокола.177178## 18.5.5.5. IncompleteReadError179180#### `exception asyncio.IncompleteReadError`181182> Ошибка неполного чтения, подкласс183>184> [`EOFError`](https://python-all.ru/3.4/library/exceptions.html#EOFError)185>186> .187188#### `expected`189190Общее количество ожидаемых байт ([`int`](https://python-all.ru/3.4/library/functions.html#int)).191192#### `partial`193194Строка байтов прочитана до достижения конца потока ([`байты`](https://python-all.ru/3.4/library/functions.html#bytes)).195196## 18.5.5.6. Примеры работы с потоками197198### 18.5.5.6.1. TCP-эхо-клиент с использованием потоков199200TCP-эхо-клиент, использующий функцию [`asyncio.open_connection()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.open_connection):201202```python203import asyncio204205@asyncio.coroutine206def tcp_echo_client(message, loop):207    reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888,208                                                        loop=loop)209210    print('Send: %r' % message)211    writer.write(message.encode())212213    data = yield from reader.read(100)214    print('Received: %r' % data.decode())215216    print('Close the socket')217    writer.close()218219message = 'Hello World!'220loop = asyncio.get_event_loop()221loop.run_until_complete(tcp_echo_client(message, loop))222loop.close()223```224225> **См. также**226>227> Пример [*протокола TCP-эхо-клиента*](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio-tcp-echo-client-protocol) использует метод [`BaseEventLoop.create_connection()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_connection).228229### 18.5.5.6.2. TCP-эхо-сервер с использованием потоков230231TCP-эхо-сервер, использующий функцию [`asyncio.start_server()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.start_server):232233```python234import asyncio235236@asyncio.coroutine237def handle_echo(reader, writer):238    data = yield from reader.read(100)239    message = data.decode()240    addr = writer.get_extra_info('peername')241    print("Received %r from %r" % (message, addr))242243    print("Send: %r" % message)244    writer.write(data)245    yield from writer.drain()246247    print("Close the client socket")248    writer.close()249250loop = asyncio.get_event_loop()251coro = asyncio.start_server(handle_echo, '127.0.0.1', 8888, loop=loop)252server = loop.run_until_complete(coro)253254# Обслуживать запросы до нажатия Ctrl+C255print('Serving on {}'.format(server.sockets[0].getsockname()))256try:257    loop.run_forever()258except KeyboardInterrupt:259    pass260261# Закрыть сервер262server.close()263loop.run_until_complete(server.wait_closed())264loop.close()265```266267> **См. также**268>269> Пример [*протокола TCP-эхо-сервера*](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio-tcp-echo-server-protocol) использует метод [`BaseEventLoop.create_server()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_server).270271### 18.5.5.6.3. Получение HTTP-заголовков272273Простой пример получения HTTP-заголовков URL, переданного в командной строке:274275```python276import asyncio277import urllib.parse278import sys279280@asyncio.coroutine281def print_http_headers(url):282    url = urllib.parse.urlsplit(url)283    if url.scheme == 'https':284        connect = asyncio.open_connection(url.hostname, 443, ssl=True)285    else:286        connect = asyncio.open_connection(url.hostname, 80)287    reader, writer = yield from connect288    query = ('HEAD {path} HTTP/1.0\r\n'289             'Host: {hostname}\r\n'290             '\r\n').format(path=url.path or '/', hostname=url.hostname)291    writer.write(query.encode('latin-1'))292    while True:293        line = yield from reader.readline()294        if not line:295            break296        line = line.decode('latin1').rstrip()297        if line:298            print('HTTP header> %s' % line)299300    # Игнорировать тело, закрыть сокет301    writer.close()302303url = sys.argv[1]304loop = asyncio.get_event_loop()305task = asyncio.ensure_future(print_http_headers(url))306loop.run_until_complete(task)307loop.close()308```309310Использование:311312```python313python example.py http://example.com/path/page.html314```315316или с HTTPS:317318```python319python example.py https://example.com/path/page.html320```321322### 18.5.5.6.4. Регистрация открытого сокета для ожидания данных с использованием потоков323324Корутина, которая ожидает, пока сокет получит данные, используя функцию [`open_connection()`](https://python-all.ru/3.4/library/asyncio-stream.html#asyncio.open_connection):325326```python327import asyncio328try:329    from socket import socketpair330except ImportError:331    from asyncio.windows_utils import socketpair332333@asyncio.coroutine334def wait_for_data(loop):335    # Создаём пару соединённых сокетов336    rsock, wsock = socketpair()337338    # Зарегистрировать открытый сокет для ожидания данных339    reader, writer = yield from asyncio.open_connection(sock=rsock, loop=loop)340341    # Симулировать приём данных из сети342    loop.call_soon(wsock.send, 'abc'.encode())343344    # Ожидать данные345    data = yield from reader.read(100)346347    # Данные получены, всё готово: закрыть сокет348    print("Received:", data.decode())349    writer.close()350351    # Закрыть второй сокет352    wsock.close()353354loop = asyncio.get_event_loop()355loop.run_until_complete(wait_for_data(loop))356loop.close()357```358359> **См. также**360>361> Пример [*регистрации открытого сокета для ожидания данных с использованием протокола*](https://python-all.ru/3.4/library/asyncio-protocol.html#asyncio-register-socket) использует низкоуровневый протокол, созданный методом [`BaseEventLoop.create_connection()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.create_connection).362>363> Пример [*отслеживания событий чтения на файловом дескрипторе*](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio-watch-read-event) использует низкоуровневый метод [`BaseEventLoop.add_reader()`](https://python-all.ru/3.4/library/asyncio-eventloop.html#asyncio.BaseEventLoop.add_reader) для регистрации файлового дескриптора сокета.364