-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasyncio-tips.py
More file actions
81 lines (68 loc) · 3.18 KB
/
asyncio-tips.py
File metadata and controls
81 lines (68 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from os.path import isfile
from typing import NoReturn
import base64
import hashlib
import hmac
import asyncio
import aiofiles
from aiohttp import ClientSession
from aiohttp.client import _RequestContextManager
def sig_hash_msg(*, secret_message: str, secret_key: str = "private-key", digestmod=hashlib.sha256) -> str:
"""
Кодирование сообщения, используя односторонние хэш-функции типа sha2
:param secret_message: Сообщение для хэширования
:param secret_key: Ключ для хэширования
:param digestmod: Алгоритм хэширования
:return: Кодированная строка.
"""
secret_message, secret_key = bytes(secret_message, "UTF-8"), bytes(secret_key, "UTF-8")
digester = hmac.new(key=secret_key, msg=secret_message, digestmod=digestmod)
signature = digester.digest()
signature = base64.urlsafe_b64encode(signature)
return str(signature, "UTF-8")
async def save_file(*, content: bytes, path2file: str) -> NoReturn:
"""
Асинхронное сохранение файла
:param content:
:param path2file:
"""
async with aiofiles.open(path2file, mode="wb") as stream:
await stream.write(content)
def get_media_type(*, response: _RequestContextManager, default_content_type: str = "mp4") -> str:
"""
Распарсить медиа тип файла
:param response: _RequestContextManager
:return: медиа тип файла
"""
try:
return response.content_type.split("/")[-1]
except:
return default_content_type
async def download_bytes(*, url: str) -> str:
"""
Создать сессию, отправить GET запрос, проверить на статус НЕ 400.
Получить тип скачиваемого объекта (.json, .mp4, .jpg, etc).
Создать хэш из url по которому хранится файл.
Сохранить объект как ХЭШ.ТИП
Если объект находится в хранилище типа s3, то уточните, если ли время жизни у ссылок на файлы.
Если есть, то имеет смысл использовать хэширование
:param url: ссылка по которому хранится файл
:return: путь до файла
"""
async with ClientSession() as session:
async with session.get(url=url) as resp:
resp.raise_for_status()
bytes_data = await resp.read()
media_type = get_media_type(response=resp)
file_name = sig_hash_msg(secret_message=url)
path2file = f"{file_name}.{media_type}"
if not isfile(path2file):
await save_file(content=bytes_data, path2file=path2file)
return path2file
async def run_gather():
url = "https://ya.ru"
tasks = (asyncio.create_task(coro=download_bytes(url=url)) for _ in range(10))
return await asyncio.gather(*tasks, return_exceptions=True)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
answer = loop.run_until_complete(run_gather())