#python #webserver #python-asyncio #aiohttp
#python #веб-сервер #python-asyncio #aiohttp
Вопрос:
Я хочу асинхронно извлекать файл с локального хоста без веб-сервера. Кажется, что это можно сделать с помощью file:// scheme. Следующий пример кода взят из документации, но, очевидно, он не работает:
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
html = await fetch(session, 'file://localhost/Users/user/test.txt')
print(html)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Как заставить это работать?
Один из способов, который я вижу, — использовать «curl file:// path» в отдельном пуле потоков с использованием run_in_executor, но я думаю, что должен быть способ исправить код
Комментарии:
1. Если вам нужно получить содержимое локального файла, разве вы не можете просто сделать это на Python без каких-либо специальных библиотек, например
html = open('Users/user/test.txt').read()
? Если файл не очень большой, вам, вероятно, не нужно делать его асинхронным.2. Файлы большие, и это идея сделать его асинхронным, чтобы не блокировать другие асинхронные задачи
3. Тогда я бы рекомендовал сделать это, просто в функции, вызываемой через
run_in_executor
. Это буквально три строки кода, и вы не зависите ни от какой внешней программы. Другим вариантом является библиотека aiofiles, но она также использует потоки под капотом и может оказаться менее эффективной, чем «очевидный» код.4. @user4815162342, да, я понимаю, спасибо. Я подумал, что использование run_in_executor — лучший выбор здесь, и, возможно, он единственный. Большое спасибо. И последний вопрос по этому поводу: должен ли я использовать созданный цикл событий для run_in_executor или мне следует создать для него другой?
5. Как правило, «создание второго цикла событий» почти никогда не является правильным способом использования asyncio. В случае
run_in_executor
весь смысл этой функции заключается в интеграции устаревшего кода синхронизации в ваш цикл событий — если вы создали другой цикл событий только дляrun_in_executor
, вы не сможете его дождаться! Но что может иметь смысл, и, возможно, то, что вы намеревались спросить, — это создание другого исполнителя (пула потоков). Исполнитель, предоставляемый asyncio при передачеNone
в качестве первого аргументаrun_in_executor
, работает просто отлично, так что в этом тоже нет необходимости. Смотрите ответ для примера.
Ответ №1:
Если вам нужно получить содержимое локального файла, вы можете сделать это с помощью обычных встроенных программ Python, таких как:
with open('Users/user/test.txt') as rd:
html = rd.read()
Если файл не очень большой и хранится в локальной файловой системе, вам даже не нужно делать его асинхронным, поскольку его чтение будет достаточно быстрым, чтобы не нарушать цикл событий. Если файл большой или его чтение может быть медленным по другим причинам, вам следует прочитать его до конца run_in_executor
, чтобы он не блокировал другой код asyncio. Например (непроверенный):
def read_file_sync(file_name):
with open('Users/user/test.txt') as rd:
return rd.read()
async def read_file(file_name):
loop = asyncio.get_event_loop()
html = await loop.run_in_executor(None, read_file_sync, file_name)
return html
Комментарии:
1. Большое спасибо, вы мне очень помогли. Теперь я вижу