feat: 引入异步文件 I/O 避免阻塞事件循环,共享全局 httpx 连接池

This commit is contained in:
amtoaer
2023-11-24 18:31:51 +08:00
parent 27b2cd7739
commit 4dee129d38
4 changed files with 33 additions and 10 deletions

View File

@@ -5,7 +5,7 @@ import uvloop
from loguru import logger
from models import init_model
from processor import process
from processor import cleanup, process
from settings import settings
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
@@ -25,4 +25,8 @@ async def entry() -> None:
if __name__ == "__main__":
asyncio.run(entry())
with asyncio.Runner() as runner:
try:
runner.run(entry())
finally:
runner.run(cleanup())

13
poetry.lock generated
View File

@@ -1,5 +1,16 @@
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand.
[[package]]
name = "aiofiles"
version = "23.2.1"
description = "File support for asyncio."
optional = false
python-versions = ">=3.7"
files = [
{file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"},
{file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"},
]
[[package]]
name = "aiohttp"
version = "3.9.0"
@@ -1801,4 +1812,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "eb9d995cdf3732762a25c0e49cb58df7c71122646f24ba5715979c6a510d9ed1"
content-hash = "aa8b8172538f633284fb81f9cb6d1ca6644c3c104859738237965f70ccb2fb59"

View File

@@ -4,6 +4,7 @@ from asyncio import Semaphore, create_subprocess_exec
from asyncio.subprocess import DEVNULL
from pathlib import Path
import aiofiles
import httpx
from bilibili_api import HEADERS, favorite_list, video
from loguru import logger
@@ -15,6 +16,12 @@ from settings import settings
anchor = datetime.datetime.today()
client = httpx.AsyncClient(headers=HEADERS)
async def cleanup() -> None:
await client.aclose()
def concurrent_decorator(concurrency: int) -> callable:
sem = Semaphore(value=concurrency)
@@ -30,13 +37,13 @@ def concurrent_decorator(concurrency: int) -> callable:
async def download_content(url: str, path: Path):
async with httpx.AsyncClient(headers=HEADERS) as sess:
resp = await sess.get(url)
with path.open("wb") as f:
for chunk in resp.iter_bytes(1024):
if not chunk:
break
f.write(chunk)
async with client.stream("GET", url) as resp, aiofiles.open(
path, "wb"
) as f:
async for chunk in resp.aiter_bytes(40960):
if not chunk:
return
await f.write(chunk)
async def process():

View File

@@ -13,6 +13,7 @@ dataclasses-json = "0.6.2"
tortoise-orm = "0.20.0"
loguru = "0.7.2"
uvloop = "0.19.0"
aiofiles = "23.2.1"
[tool.poetry.group.dev.dependencies]