-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache_decorator.py
93 lines (73 loc) · 2.89 KB
/
cache_decorator.py
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
82
83
84
85
86
87
88
89
90
91
92
93
import hashlib
import pickle
from functools import wraps
from loguru import logger
from typing import Callable, Any, Dict, Tuple
def async_unit_cache(assert_result: Callable[[Any], bool], cache_path: str) -> Callable:
"""
异步缓存装饰器,用于缓存函数的返回值。
参数:
assert_result (Callable[[Any], bool]): 用于判断返回值是否合理的回调函数。
cache_path (str): 缓存文件的路径。
返回:
Callable: 装饰器。
"""
def decorator(func: Callable) -> Callable:
@wraps(func)
async def wrapper(*args: Tuple, **kwargs: Dict) -> Any:
try:
with open(cache_path, "rb") as f:
cache: Dict[str, Any] = pickle.load(f)
except Exception:
cache: Dict[str, Any] = {}
key: str = hashlib.sha256(str((args, kwargs)).encode()).hexdigest()
try:
result = cache[key]
assert assert_result(result)
logger.success(f"Cache hit for {func.__name__}")
except KeyError:
logger.debug(f"Cache miss for {func.__name__}")
result = await func(*args, **kwargs)
if assert_result(result):
cache[key] = result
with open(cache_path, "wb") as f:
pickle.dump(cache, f)
except Exception:
result = await func(*args, **kwargs)
return result
return wrapper
return decorator
def sync_unit_cache(assert_result: Callable[[Any], bool], cache_path: str) -> Callable:
"""
同步缓存装饰器,用于缓存函数的返回值。
参数:
assert_result (Callable[[Any], bool]): 用于判断返回值是否合理的回调函数。
cache_path (str): 缓存文件的路径。
返回:
Callable: 装饰器。
"""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args: Tuple, **kwargs: Dict) -> Any:
try:
with open(cache_path, "rb") as f:
cache: Dict[str, Any] = pickle.load(f)
except Exception:
cache: Dict[str, Any] = {}
key: str = hashlib.sha256(str((args, kwargs)).encode()).hexdigest()
try:
result = cache[key]
assert assert_result(result)
logger.success(f"Cache hit for {func.__name__}")
except KeyError:
logger.debug(f"Cache miss for {func.__name__}")
result = func(*args, **kwargs)
if assert_result(result):
cache[key] = result
with open(cache_path, "wb") as f:
pickle.dump(cache, f)
except Exception:
result = func(*args, **kwargs)
return result
return wrapper
return decorator