Повестка дня
- Цикл событий
- Создание цикла событий с помощью Asyncio
- Запись в файл с помощью Aiofiles и asyncio
Что такое цикл событий?
В программировании, основанном на событиях, цикл событий — это механизм, который позволяет программе ожидать и отправлять события или сообщения эффективным и оперативным образом. Цикл событий управляет порядком обработки событий и гарантирует своевременную реакцию программы на события.
Цикл событий в Python
В Python цикл событий часто реализуется с помощью модуля asyncio, который предоставляет инфраструктуру для написания асинхронного кода. Asyncio использует сопрограммы, функции, которые можно приостанавливать и возобновлять, для представления задач, которые могут выполняться одновременно. Цикл событий работает непрерывно, проверяя события и планируя выполнение задач по мере необходимости.
Когда происходит событие, такое как пользовательский ввод или сетевое соединение, цикл событий сигнализирует соответствующей задаче о возобновлении выполнения. Затем задача может обработать событие и создать новые события или задачи. Это позволяет программе одновременно реагировать на несколько событий, не блокируя и не ожидая завершения каждого события перед обработкой следующего.
Цикл событий в Python с Asyncio
Вот пример использования asyncio в Python для реализации простого веб-сервера, который прослушивает HTTP-запросы и отвечает сообщением. Создайте новый файл event_loop.py
и вставьте следующий код:
import asyncio async def handle_request(reader, writer): request = (await reader.read()).decode('utf-8') print("Handling request") print(request) headers = ( b'HTTP/1.1 200 OK\r\n' b'Content-Type: text/plain\r\n' b'Access-Control-Allow-Origin: *\r\n' b'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS\r\n' b'Access-Control-Allow-Headers: Content-Type\r\n\r\n' ) response = b'Hello, world!' writer.write(headers + response) await writer.drain() writer.close() print("Request processed") async def main(): server = await asyncio.start_server(handle_request, 'localhost', 8000) print(f'Server running on {server.sockets[0].getsockname()}') async with server: await server.serve_forever() loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: loop.close()
Функция async def handle_request(reader, writer)
является обработчиком запросов. Он получает два параметра: reader
и writer
. reader
— это объект StreamReader
, который считывает входящие данные от клиента, а writer
— это объект StreamWriter
, который записывает данные обратно клиенту.
Функция считывает входящий запрос от клиента с помощью reader.read()
, который возвращает сопрограмму, которая считывает до 64 КБ данных от клиента. Затем он декодирует данные, используя decode('utf-8')
, чтобы преобразовать их из байтов в строку.
После печати запроса функция формирует заголовок и тело ответа HTTP и отправляет их обратно клиенту с помощью метода writer.write()
. Затем вызывается метод drain()
для передачи данных клиенту, а метод writer.close()
вызывается для закрытия соединения.
Функция async def main()
— это основная сопрограмма, запускающая сервер с помощью asyncio.start_server()
. Затем он выводит на консоль сообщение о том, что сервер работает, а затем входит в бесконечный цикл, используя server.serve_forever()
для ожидания входящих клиентских запросов.
Затем цикл событий извлекается с использованием asyncio.get_event_loop()
, а основная сопрограмма выполняется с использованием loop.run_until_complete()
. Наконец, цикл событий закрывается с помощью loop.close()
. Запустите файл с помощью:
python3 event_loop.py
Чтение и письмо — Asyncio-Ex-2
Вот еще один пример использования asyncio и цикла обработки событий для выполнения асинхронных операций ввода-вывода, таких как чтение и запись в файл.
Установите aiofiles и библиотеки asyncio python:
pip install aiofiles asyncio
Создайте файл example.txt
в корневой папке. Создайте новый файл event_loop_file_writer.py
в том же каталоге и введите следующий код:
import asyncio import aiofiles # Define an async function to write data to a file async def write_to_file(filename, data): # Open the file for writing using async with, which ensures the file is closed # when we're done with it async with aiofiles.open(filename, 'w') as f: # Write the data to the file using the await keyword await f.write(data) # Define an async function to read data from a file async def read_from_file(filename): # Open the file for reading using async with, which ensures the file is closed # when we're done with it async with aiofiles.open(filename, 'r') as f: # Read the contents of the file using the await keyword data = await f.read() # Return the data as a string return data # Define the main coroutine, which will run when we execute the script async def main(): # Set up a filename and some data to write to the file filename = 'example.txt' data = 'Hello, world!' # Create tasks to write and read the file concurrently write_task = asyncio.create_task(write_to_file(filename, data)) read_task = asyncio.create_task(read_from_file(filename)) # Wait for both tasks to complete await asyncio.gather(write_task, read_task) # Print the contents of the file to the console print(read_task.result()) # Run the main coroutine using asyncio.run, which creates and manages the event loop if __name__ == '__main__': asyncio.run(main())
Этот код определяет три асинхронные функции: write_to_file
, read_from_file
и main
.
write_to_file
принимает два аргумента: filename
и data
. Он использует библиотеку aiofiles
, чтобы открыть файл в режиме записи и записать данные в файл, используя await f.write(data)
.
read_from_file
принимает один аргумент filename
. Он открывает файл в режиме чтения, используя библиотеку aiofiles
, считывает содержимое файла, используя await f.read()
, и возвращает данные в виде строки.
main
устанавливает имя файла и некоторые данные для записи в файл. Затем он создает две задачи для одновременной записи и чтения файла с использованием asyncio.create_task()
. Он ожидает завершения обеих задач с помощью asyncio.gather()
и, наконец, выводит содержимое файла на консоль.
Сценарий запускает сопрограмму main
, используя asyncio.run()
, которая создает цикл обработки событий и управляет им. Когда скрипт выполняется напрямую, он запускает сопрограмму main
. Запустите этот файл с помощью:
python3 event_loop_file_writer.py
Если исходный текстовый файл — example.txt, проверьте его еще раз после запуска кода. вы сможете увидеть обновленный файл.
Где находится цикл обработки событий в приведенном выше примере кода?
Функция asyncio.run()
создает цикл обработки событий, запускает переданную ей сопрограмму, а затем закрывает цикл обработки событий после завершения сопрограммы. Это позволяет легко управлять циклом обработки событий и упрощает асинхронное программирование.
Весь код приведенного выше примера доступен здесь, на Github:
Заключение
В заключение, цикл событий — это механизм, который позволяет программе ожидать и отправлять события или сообщения эффективно и оперативно. В Python модуль asyncio предоставляет инфраструктуру для написания асинхронного кода с использованием сопрограмм. Asyncio позволяет программам реагировать на несколько событий одновременно, не блокируя и не ожидая завершения каждого события перед обработкой следующего. В этой статье мы рассмотрели, как создать цикл событий с помощью asyncio и как использовать его для написания простого веб-сервера, который прослушивает HTTP-запросы и отвечает сообщением. Мы также изучили, как использовать asyncio и цикл событий для выполнения асинхронных операций ввода-вывода, таких как чтение и запись в файл. На этих примерах вы можете увидеть, насколько мощным может быть asyncio при написании эффективных и отзывчивых программ.
Это все для этой статьи! Не стесняйтесь оставлять отзывы или вопросы в комментариях. Если вы нашли это захватывающим чтением, хлопайте в ладоши и подписывайтесь! Ваше здоровье!