hutool-python 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hutool/__init__.py +174 -0
- hutool/cache/__init__.py +7 -0
- hutool/cache/cache_util.py +47 -0
- hutool/cache/fifo_cache.py +87 -0
- hutool/cache/lfu_cache.py +129 -0
- hutool/cache/lru_cache.py +93 -0
- hutool/cache/timed_cache.py +115 -0
- hutool/captcha/__init__.py +3 -0
- hutool/captcha/captcha_util.py +215 -0
- hutool/core/__init__.py +23 -0
- hutool/core/_base.py +61 -0
- hutool/core/bean.py +214 -0
- hutool/core/codec.py +111 -0
- hutool/core/coll.py +635 -0
- hutool/core/date.py +1024 -0
- hutool/core/exceptions.py +66 -0
- hutool/core/io/__init__.py +0 -0
- hutool/core/io/data_size_util.py +79 -0
- hutool/core/io/file_name_util.py +111 -0
- hutool/core/io/file_util.py +650 -0
- hutool/core/io/io_util.py +133 -0
- hutool/core/io/path_util.py +247 -0
- hutool/core/io/resource_util.py +137 -0
- hutool/core/map.py +933 -0
- hutool/core/math_util.py +105 -0
- hutool/core/net.py +288 -0
- hutool/core/text/__init__.py +0 -0
- hutool/core/text/csv_util.py +54 -0
- hutool/core/text/str_builder.py +224 -0
- hutool/core/text/unicode_util.py +58 -0
- hutool/core/tree.py +242 -0
- hutool/core/util/__init__.py +63 -0
- hutool/core/util/array_util.py +503 -0
- hutool/core/util/boolean_util.py +124 -0
- hutool/core/util/charset_util.py +60 -0
- hutool/core/util/class_util.py +136 -0
- hutool/core/util/coordinate_util.py +186 -0
- hutool/core/util/credit_code_util.py +110 -0
- hutool/core/util/desensitized_util.py +194 -0
- hutool/core/util/enum_util.py +94 -0
- hutool/core/util/escape_util.py +97 -0
- hutool/core/util/hash_util.py +243 -0
- hutool/core/util/hex_util.py +140 -0
- hutool/core/util/id_util.py +147 -0
- hutool/core/util/idcard_util.py +300 -0
- hutool/core/util/number_util.py +720 -0
- hutool/core/util/object_util.py +294 -0
- hutool/core/util/page_util.py +61 -0
- hutool/core/util/phone_util.py +140 -0
- hutool/core/util/random_util.py +112 -0
- hutool/core/util/re_util.py +231 -0
- hutool/core/util/reflect_util.py +135 -0
- hutool/core/util/runtime_util.py +89 -0
- hutool/core/util/str_util.py +2320 -0
- hutool/core/util/system_util.py +62 -0
- hutool/core/util/url_util.py +232 -0
- hutool/core/util/version_util.py +41 -0
- hutool/core/util/xml_util.py +158 -0
- hutool/core/util/zip_util.py +126 -0
- hutool/cron/__init__.py +4 -0
- hutool/cron/cron_pattern.py +123 -0
- hutool/cron/cron_util.py +115 -0
- hutool/crypto/__init__.py +5 -0
- hutool/crypto/digest_util.py +167 -0
- hutool/crypto/secure_util.py +311 -0
- hutool/crypto/sign_util.py +74 -0
- hutool/dfa/__init__.py +3 -0
- hutool/dfa/sensitive_util.py +114 -0
- hutool/extra/__init__.py +6 -0
- hutool/extra/emoji_util.py +90 -0
- hutool/extra/pinyin_util.py +44 -0
- hutool/extra/qr_code_util.py +58 -0
- hutool/extra/template_util.py +41 -0
- hutool/http/__init__.py +6 -0
- hutool/http/html_util.py +88 -0
- hutool/http/http_request.py +188 -0
- hutool/http/http_response.py +139 -0
- hutool/http/http_util.py +237 -0
- hutool/json_util.py +251 -0
- hutool/jwt_util.py +57 -0
- hutool/setting/__init__.py +5 -0
- hutool/setting/props_util.py +79 -0
- hutool/setting/setting_util.py +80 -0
- hutool/setting/yaml_util.py +45 -0
- hutool_python-1.0.0.dist-info/LICENSE +127 -0
- hutool_python-1.0.0.dist-info/METADATA +438 -0
- hutool_python-1.0.0.dist-info/RECORD +89 -0
- hutool_python-1.0.0.dist-info/WHEEL +5 -0
- hutool_python-1.0.0.dist-info/top_level.txt +1 -0
hutool/__init__.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""Hutool-Python - Java Hutool 的 Python 移植版工具库。
|
|
2
|
+
|
|
3
|
+
全量移植 Java Hutool 的 Python 版工具库,涵盖:
|
|
4
|
+
- core: 核心工具类(字符串、数字、集合、日期、IO、Bean、编解码等)
|
|
5
|
+
- http: HTTP 客户端工具
|
|
6
|
+
- json_util: JSON 工具
|
|
7
|
+
- crypto: 加密工具(摘要、对称/非对称加密、签名)
|
|
8
|
+
- cache: 缓存工具(FIFO、LFU、LRU、定时)
|
|
9
|
+
- captcha: 验证码
|
|
10
|
+
- dfa: 敏感词过滤
|
|
11
|
+
- extra: 扩展工具(拼音、Emoji、模板、二维码)
|
|
12
|
+
- cron: 定时任务
|
|
13
|
+
- jwt_util: JWT 工具
|
|
14
|
+
- setting: 配置工具(YAML、Properties)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__version__ = "1.0.0"
|
|
18
|
+
|
|
19
|
+
# 核心工具类 - 顶层快捷导入
|
|
20
|
+
from .core.bean import BeanUtil
|
|
21
|
+
from .core.codec import Base32, Base64
|
|
22
|
+
from .core.coll import CollUtil, ListUtil
|
|
23
|
+
from .core.date import DateTime, DateUtil
|
|
24
|
+
from .core.io.data_size_util import DataSizeUtil
|
|
25
|
+
from .core.io.file_name_util import FileNameUtil
|
|
26
|
+
from .core.io.file_util import FileUtil
|
|
27
|
+
from .core.io.io_util import IoUtil
|
|
28
|
+
from .core.io.path_util import PathUtil
|
|
29
|
+
from .core.io.resource_util import ResourceUtil
|
|
30
|
+
from .core.map import BiMap, DictUtil, MapUtil
|
|
31
|
+
from .core.math_util import BitStatusUtil, MathUtil
|
|
32
|
+
from .core.net import Ipv4Util, MaskBit, NetUtil
|
|
33
|
+
from .core.text.csv_util import CsvUtil
|
|
34
|
+
from .core.text.str_builder import StrBuilder
|
|
35
|
+
from .core.text.unicode_util import UnicodeUtil
|
|
36
|
+
from .core.tree import TreeNode, TreeUtil
|
|
37
|
+
from .core.util.array_util import ArrayUtil
|
|
38
|
+
from .core.util.boolean_util import BooleanUtil
|
|
39
|
+
from .core.util.charset_util import CharsetUtil
|
|
40
|
+
from .core.util.class_util import ClassUtil
|
|
41
|
+
from .core.util.coordinate_util import Coordinate, CoordinateUtil
|
|
42
|
+
from .core.util.credit_code_util import CreditCodeUtil
|
|
43
|
+
from .core.util.desensitized_util import DesensitizedUtil
|
|
44
|
+
from .core.util.enum_util import EnumUtil
|
|
45
|
+
from .core.util.escape_util import EscapeUtil
|
|
46
|
+
from .core.util.hash_util import HashUtil
|
|
47
|
+
from .core.util.hex_util import HexUtil
|
|
48
|
+
from .core.util.id_util import IdUtil
|
|
49
|
+
from .core.util.idcard_util import IdcardUtil
|
|
50
|
+
from .core.util.number_util import NumberUtil
|
|
51
|
+
from .core.util.object_util import ObjectUtil
|
|
52
|
+
from .core.util.page_util import PageUtil
|
|
53
|
+
from .core.util.phone_util import PhoneUtil
|
|
54
|
+
from .core.util.random_util import RandomUtil
|
|
55
|
+
from .core.util.re_util import ReUtil
|
|
56
|
+
from .core.util.reflect_util import ReflectUtil
|
|
57
|
+
from .core.util.runtime_util import RuntimeUtil
|
|
58
|
+
from .core.util.str_util import CharPool, CharUtil, StrUtil
|
|
59
|
+
from .core.util.system_util import SystemUtil
|
|
60
|
+
from .core.util.url_util import URLUtil
|
|
61
|
+
from .core.util.version_util import VersionUtil
|
|
62
|
+
from .core.util.xml_util import XmlUtil
|
|
63
|
+
from .core.util.zip_util import ZipUtil
|
|
64
|
+
|
|
65
|
+
# 其他模块
|
|
66
|
+
from .cache import CacheUtil, FIFOCache, LFUCache, LRUCache, TimedCache
|
|
67
|
+
from .captcha import ArithmeticCaptcha, CaptchaUtil, LineCaptcha
|
|
68
|
+
from .crypto import DigestUtil, SecureUtil, SignUtil
|
|
69
|
+
from .cron import CronPattern, CronUtil
|
|
70
|
+
from .dfa import SensitiveUtil
|
|
71
|
+
from .extra import EmojiUtil, PinyinUtil, QrCodeUtil, TemplateUtil
|
|
72
|
+
from .http import HtmlUtil, HttpRequest, HttpResponse, HttpUtil
|
|
73
|
+
from .json_util import JSONUtil
|
|
74
|
+
from .jwt_util import JWTUtil
|
|
75
|
+
from .setting import PropsUtil, SettingUtil, YamlUtil
|
|
76
|
+
|
|
77
|
+
__all__ = [
|
|
78
|
+
# core/util
|
|
79
|
+
"ArrayUtil",
|
|
80
|
+
"BooleanUtil",
|
|
81
|
+
"CharsetUtil",
|
|
82
|
+
"CharPool",
|
|
83
|
+
"CharUtil",
|
|
84
|
+
"ClassUtil",
|
|
85
|
+
"Coordinate",
|
|
86
|
+
"CoordinateUtil",
|
|
87
|
+
"CreditCodeUtil",
|
|
88
|
+
"DesensitizedUtil",
|
|
89
|
+
"EnumUtil",
|
|
90
|
+
"EscapeUtil",
|
|
91
|
+
"HashUtil",
|
|
92
|
+
"HexUtil",
|
|
93
|
+
"IdUtil",
|
|
94
|
+
"IdcardUtil",
|
|
95
|
+
"NumberUtil",
|
|
96
|
+
"ObjectUtil",
|
|
97
|
+
"PageUtil",
|
|
98
|
+
"PhoneUtil",
|
|
99
|
+
"RandomUtil",
|
|
100
|
+
"ReUtil",
|
|
101
|
+
"ReflectUtil",
|
|
102
|
+
"RuntimeUtil",
|
|
103
|
+
"StrUtil",
|
|
104
|
+
"SystemUtil",
|
|
105
|
+
"URLUtil",
|
|
106
|
+
"VersionUtil",
|
|
107
|
+
"XmlUtil",
|
|
108
|
+
"ZipUtil",
|
|
109
|
+
# core/io
|
|
110
|
+
"DataSizeUtil",
|
|
111
|
+
"FileNameUtil",
|
|
112
|
+
"FileUtil",
|
|
113
|
+
"IoUtil",
|
|
114
|
+
"PathUtil",
|
|
115
|
+
"ResourceUtil",
|
|
116
|
+
# core/text
|
|
117
|
+
"CsvUtil",
|
|
118
|
+
"StrBuilder",
|
|
119
|
+
"UnicodeUtil",
|
|
120
|
+
# core 其他
|
|
121
|
+
"Base32",
|
|
122
|
+
"Base64",
|
|
123
|
+
"BeanUtil",
|
|
124
|
+
"BiMap",
|
|
125
|
+
"BitStatusUtil",
|
|
126
|
+
"CollUtil",
|
|
127
|
+
"DateTime",
|
|
128
|
+
"DateUtil",
|
|
129
|
+
"DictUtil",
|
|
130
|
+
"Ipv4Util",
|
|
131
|
+
"ListUtil",
|
|
132
|
+
"MapUtil",
|
|
133
|
+
"MaskBit",
|
|
134
|
+
"MathUtil",
|
|
135
|
+
"NetUtil",
|
|
136
|
+
"TreeNode",
|
|
137
|
+
"TreeUtil",
|
|
138
|
+
# http
|
|
139
|
+
"HtmlUtil",
|
|
140
|
+
"HttpRequest",
|
|
141
|
+
"HttpResponse",
|
|
142
|
+
"HttpUtil",
|
|
143
|
+
# json / jwt
|
|
144
|
+
"JSONUtil",
|
|
145
|
+
"JWTUtil",
|
|
146
|
+
# cache
|
|
147
|
+
"CacheUtil",
|
|
148
|
+
"FIFOCache",
|
|
149
|
+
"LFUCache",
|
|
150
|
+
"LRUCache",
|
|
151
|
+
"TimedCache",
|
|
152
|
+
# captcha
|
|
153
|
+
"ArithmeticCaptcha",
|
|
154
|
+
"CaptchaUtil",
|
|
155
|
+
"LineCaptcha",
|
|
156
|
+
# crypto
|
|
157
|
+
"DigestUtil",
|
|
158
|
+
"SecureUtil",
|
|
159
|
+
"SignUtil",
|
|
160
|
+
# cron
|
|
161
|
+
"CronPattern",
|
|
162
|
+
"CronUtil",
|
|
163
|
+
# dfa
|
|
164
|
+
"SensitiveUtil",
|
|
165
|
+
# extra
|
|
166
|
+
"EmojiUtil",
|
|
167
|
+
"PinyinUtil",
|
|
168
|
+
"QrCodeUtil",
|
|
169
|
+
"TemplateUtil",
|
|
170
|
+
# setting
|
|
171
|
+
"PropsUtil",
|
|
172
|
+
"SettingUtil",
|
|
173
|
+
"YamlUtil",
|
|
174
|
+
]
|
hutool/cache/__init__.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from .fifo_cache import FIFOCache
|
|
2
|
+
from .lfu_cache import LFUCache
|
|
3
|
+
from .lru_cache import LRUCache
|
|
4
|
+
from .timed_cache import TimedCache
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CacheUtil:
|
|
8
|
+
"""缓存工厂类。
|
|
9
|
+
|
|
10
|
+
提供各种缓存实现的便捷创建方法。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def new_fifo_cache(capacity: int = 16) -> FIFOCache:
|
|
15
|
+
"""创建FIFO(先进先出)缓存。
|
|
16
|
+
|
|
17
|
+
:param capacity: 缓存最大容量,默认16
|
|
18
|
+
:return: FIFOCache实例
|
|
19
|
+
"""
|
|
20
|
+
return FIFOCache(capacity)
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def new_lfu_cache(capacity: int = 16) -> LFUCache:
|
|
24
|
+
"""创建LFU(最不经常使用)缓存。
|
|
25
|
+
|
|
26
|
+
:param capacity: 缓存最大容量,默认16
|
|
27
|
+
:return: LFUCache实例
|
|
28
|
+
"""
|
|
29
|
+
return LFUCache(capacity)
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def new_lru_cache(capacity: int = 16) -> LRUCache:
|
|
33
|
+
"""创建LRU(最近最少使用)缓存。
|
|
34
|
+
|
|
35
|
+
:param capacity: 缓存最大容量,默认16
|
|
36
|
+
:return: LRUCache实例
|
|
37
|
+
"""
|
|
38
|
+
return LRUCache(capacity)
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def new_timed_cache(timeout: int = 60) -> TimedCache:
|
|
42
|
+
"""创建定时缓存。
|
|
43
|
+
|
|
44
|
+
:param timeout: 默认过期时间(秒),默认60秒
|
|
45
|
+
:return: TimedCache实例
|
|
46
|
+
"""
|
|
47
|
+
return TimedCache(timeout)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from typing import Any, KeysView
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FIFOCache:
|
|
6
|
+
"""FIFO(先进先出)缓存实现。
|
|
7
|
+
|
|
8
|
+
当缓存满时,最早插入的元素会被淘汰。
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, capacity: int = 16) -> None:
|
|
12
|
+
"""初始化FIFO缓存。
|
|
13
|
+
|
|
14
|
+
:param capacity: 缓存最大容量,默认16
|
|
15
|
+
"""
|
|
16
|
+
self._capacity: int = capacity
|
|
17
|
+
self._cache: OrderedDict = OrderedDict()
|
|
18
|
+
|
|
19
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
20
|
+
"""获取缓存值。
|
|
21
|
+
|
|
22
|
+
:param key: 缓存键
|
|
23
|
+
:param default: 键不存在时返回的默认值
|
|
24
|
+
:return: 缓存值,不存在时返回默认值
|
|
25
|
+
"""
|
|
26
|
+
return self._cache.get(key, default)
|
|
27
|
+
|
|
28
|
+
def put(self, key: Any, value: Any) -> None:
|
|
29
|
+
"""放入缓存。如果缓存已满,淘汰最早插入的元素。
|
|
30
|
+
|
|
31
|
+
:param key: 缓存键
|
|
32
|
+
:param value: 缓存值
|
|
33
|
+
"""
|
|
34
|
+
if key in self._cache:
|
|
35
|
+
self._cache[key] = value
|
|
36
|
+
return
|
|
37
|
+
if len(self._cache) >= self._capacity:
|
|
38
|
+
self._cache.popitem(last=False)
|
|
39
|
+
self._cache[key] = value
|
|
40
|
+
|
|
41
|
+
def remove(self, key: Any) -> Any:
|
|
42
|
+
"""移除指定键的缓存。
|
|
43
|
+
|
|
44
|
+
:param key: 缓存键
|
|
45
|
+
:return: 被移除的值,键不存在时返回None
|
|
46
|
+
"""
|
|
47
|
+
return self._cache.pop(key, None)
|
|
48
|
+
|
|
49
|
+
def size(self) -> int:
|
|
50
|
+
"""获取当前缓存大小。
|
|
51
|
+
|
|
52
|
+
:return: 当前缓存条目数
|
|
53
|
+
"""
|
|
54
|
+
return len(self._cache)
|
|
55
|
+
|
|
56
|
+
def capacity(self) -> int:
|
|
57
|
+
"""获取缓存最大容量。
|
|
58
|
+
|
|
59
|
+
:return: 缓存最大容量
|
|
60
|
+
"""
|
|
61
|
+
return self._capacity
|
|
62
|
+
|
|
63
|
+
def clear(self) -> None:
|
|
64
|
+
"""清空所有缓存。"""
|
|
65
|
+
self._cache.clear()
|
|
66
|
+
|
|
67
|
+
def is_full(self) -> bool:
|
|
68
|
+
"""判断缓存是否已满。
|
|
69
|
+
|
|
70
|
+
:return: 缓存已满返回True,否则返回False
|
|
71
|
+
"""
|
|
72
|
+
return len(self._cache) >= self._capacity
|
|
73
|
+
|
|
74
|
+
def keys(self) -> KeysView:
|
|
75
|
+
"""获取所有缓存键。
|
|
76
|
+
|
|
77
|
+
:return: 缓存键的视图
|
|
78
|
+
"""
|
|
79
|
+
return self._cache.keys()
|
|
80
|
+
|
|
81
|
+
def __contains__(self, key: Any) -> bool:
|
|
82
|
+
"""判断键是否存在于缓存中。"""
|
|
83
|
+
return key in self._cache
|
|
84
|
+
|
|
85
|
+
def __len__(self) -> int:
|
|
86
|
+
"""返回缓存大小。"""
|
|
87
|
+
return len(self._cache)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class LFUCache:
|
|
6
|
+
"""LFU(最不经常使用)缓存实现。
|
|
7
|
+
|
|
8
|
+
当缓存满时,访问频率最低的元素会被淘汰。
|
|
9
|
+
若有多个元素频率相同,淘汰最早插入的。
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, capacity: int = 16) -> None:
|
|
13
|
+
"""初始化LFU缓存。
|
|
14
|
+
|
|
15
|
+
:param capacity: 缓存最大容量,默认16
|
|
16
|
+
"""
|
|
17
|
+
self._capacity: int = capacity
|
|
18
|
+
self._cache: dict = {} # key -> value
|
|
19
|
+
self._freq: dict = {} # key -> frequency
|
|
20
|
+
self._freq_to_keys: dict = defaultdict(list) # frequency -> [keys]
|
|
21
|
+
self._min_freq: int = 0
|
|
22
|
+
|
|
23
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
24
|
+
"""获取缓存值,并更新访问频率。
|
|
25
|
+
|
|
26
|
+
:param key: 缓存键
|
|
27
|
+
:param default: 键不存在时返回的默认值
|
|
28
|
+
:return: 缓存值,不存在时返回默认值
|
|
29
|
+
"""
|
|
30
|
+
if key not in self._cache:
|
|
31
|
+
return default
|
|
32
|
+
self._update_freq(key)
|
|
33
|
+
return self._cache[key]
|
|
34
|
+
|
|
35
|
+
def put(self, key: Any, value: Any) -> None:
|
|
36
|
+
"""放入缓存。如果缓存已满,淘汰访问频率最低的元素。
|
|
37
|
+
|
|
38
|
+
:param key: 缓存键
|
|
39
|
+
:param value: 缓存值
|
|
40
|
+
"""
|
|
41
|
+
if self._capacity <= 0:
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
if key in self._cache:
|
|
45
|
+
self._cache[key] = value
|
|
46
|
+
self._update_freq(key)
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if len(self._cache) >= self._capacity:
|
|
50
|
+
self._evict()
|
|
51
|
+
|
|
52
|
+
self._cache[key] = value
|
|
53
|
+
self._freq[key] = 1
|
|
54
|
+
self._freq_to_keys[1].append(key)
|
|
55
|
+
self._min_freq = 1
|
|
56
|
+
|
|
57
|
+
def remove(self, key: Any) -> Any:
|
|
58
|
+
"""移除指定键的缓存。
|
|
59
|
+
|
|
60
|
+
:param key: 缓存键
|
|
61
|
+
:return: 被移除的值,键不存在时返回None
|
|
62
|
+
"""
|
|
63
|
+
if key not in self._cache:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
freq = self._freq[key]
|
|
67
|
+
self._freq_to_keys[freq].remove(key)
|
|
68
|
+
if not self._freq_to_keys[freq]:
|
|
69
|
+
del self._freq_to_keys[freq]
|
|
70
|
+
if self._min_freq == freq:
|
|
71
|
+
self._min_freq = min(self._freq_to_keys.keys()) if self._freq_to_keys else 0
|
|
72
|
+
|
|
73
|
+
value = self._cache[key]
|
|
74
|
+
del self._cache[key]
|
|
75
|
+
del self._freq[key]
|
|
76
|
+
return value
|
|
77
|
+
|
|
78
|
+
def size(self) -> int:
|
|
79
|
+
"""获取当前缓存大小。
|
|
80
|
+
|
|
81
|
+
:return: 当前缓存条目数
|
|
82
|
+
"""
|
|
83
|
+
return len(self._cache)
|
|
84
|
+
|
|
85
|
+
def capacity(self) -> int:
|
|
86
|
+
"""获取缓存最大容量。
|
|
87
|
+
|
|
88
|
+
:return: 缓存最大容量
|
|
89
|
+
"""
|
|
90
|
+
return self._capacity
|
|
91
|
+
|
|
92
|
+
def clear(self) -> None:
|
|
93
|
+
"""清空所有缓存。"""
|
|
94
|
+
self._cache.clear()
|
|
95
|
+
self._freq.clear()
|
|
96
|
+
self._freq_to_keys.clear()
|
|
97
|
+
self._min_freq = 0
|
|
98
|
+
|
|
99
|
+
def is_full(self) -> bool:
|
|
100
|
+
"""判断缓存是否已满。
|
|
101
|
+
|
|
102
|
+
:return: 缓存已满返回True,否则返回False
|
|
103
|
+
"""
|
|
104
|
+
return len(self._cache) >= self._capacity
|
|
105
|
+
|
|
106
|
+
def _update_freq(self, key: Any) -> None:
|
|
107
|
+
"""更新键的访问频率。
|
|
108
|
+
|
|
109
|
+
:param key: 缓存键
|
|
110
|
+
"""
|
|
111
|
+
freq = self._freq[key]
|
|
112
|
+
self._freq_to_keys[freq].remove(key)
|
|
113
|
+
if not self._freq_to_keys[freq]:
|
|
114
|
+
del self._freq_to_keys[freq]
|
|
115
|
+
if self._min_freq == freq:
|
|
116
|
+
self._min_freq = freq + 1
|
|
117
|
+
|
|
118
|
+
new_freq = freq + 1
|
|
119
|
+
self._freq[key] = new_freq
|
|
120
|
+
self._freq_to_keys[new_freq].append(key)
|
|
121
|
+
|
|
122
|
+
def _evict(self) -> None:
|
|
123
|
+
"""淘汰访问频率最低且最早插入的元素。"""
|
|
124
|
+
keys = self._freq_to_keys[self._min_freq]
|
|
125
|
+
evict_key = keys.pop(0)
|
|
126
|
+
if not keys:
|
|
127
|
+
del self._freq_to_keys[self._min_freq]
|
|
128
|
+
del self._cache[evict_key]
|
|
129
|
+
del self._freq[evict_key]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from typing import Any, KeysView
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class LRUCache:
|
|
6
|
+
"""LRU(最近最少使用)缓存实现。
|
|
7
|
+
|
|
8
|
+
当缓存满时,最近最少使用的元素会被淘汰。
|
|
9
|
+
每次get操作会将元素移至最新位置。
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, capacity: int = 16) -> None:
|
|
13
|
+
"""初始化LRU缓存。
|
|
14
|
+
|
|
15
|
+
:param capacity: 缓存最大容量,默认16
|
|
16
|
+
"""
|
|
17
|
+
self._capacity: int = capacity
|
|
18
|
+
self._cache: OrderedDict = OrderedDict()
|
|
19
|
+
|
|
20
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
21
|
+
"""获取缓存值,并将该元素移至最新位置。
|
|
22
|
+
|
|
23
|
+
:param key: 缓存键
|
|
24
|
+
:param default: 键不存在时返回的默认值
|
|
25
|
+
:return: 缓存值,不存在时返回默认值
|
|
26
|
+
"""
|
|
27
|
+
if key not in self._cache:
|
|
28
|
+
return default
|
|
29
|
+
self._cache.move_to_end(key)
|
|
30
|
+
return self._cache[key]
|
|
31
|
+
|
|
32
|
+
def put(self, key: Any, value: Any) -> None:
|
|
33
|
+
"""放入缓存。如果键已存在则更新并移至最新位置;
|
|
34
|
+
如果缓存已满,淘汰最近最少使用的元素。
|
|
35
|
+
|
|
36
|
+
:param key: 缓存键
|
|
37
|
+
:param value: 缓存值
|
|
38
|
+
"""
|
|
39
|
+
if key in self._cache:
|
|
40
|
+
self._cache.move_to_end(key)
|
|
41
|
+
self._cache[key] = value
|
|
42
|
+
return
|
|
43
|
+
if len(self._cache) >= self._capacity:
|
|
44
|
+
self._cache.popitem(last=False)
|
|
45
|
+
self._cache[key] = value
|
|
46
|
+
|
|
47
|
+
def remove(self, key: Any) -> Any:
|
|
48
|
+
"""移除指定键的缓存。
|
|
49
|
+
|
|
50
|
+
:param key: 缓存键
|
|
51
|
+
:return: 被移除的值,键不存在时返回None
|
|
52
|
+
"""
|
|
53
|
+
return self._cache.pop(key, None)
|
|
54
|
+
|
|
55
|
+
def size(self) -> int:
|
|
56
|
+
"""获取当前缓存大小。
|
|
57
|
+
|
|
58
|
+
:return: 当前缓存条目数
|
|
59
|
+
"""
|
|
60
|
+
return len(self._cache)
|
|
61
|
+
|
|
62
|
+
def capacity(self) -> int:
|
|
63
|
+
"""获取缓存最大容量。
|
|
64
|
+
|
|
65
|
+
:return: 缓存最大容量
|
|
66
|
+
"""
|
|
67
|
+
return self._capacity
|
|
68
|
+
|
|
69
|
+
def clear(self) -> None:
|
|
70
|
+
"""清空所有缓存。"""
|
|
71
|
+
self._cache.clear()
|
|
72
|
+
|
|
73
|
+
def is_full(self) -> bool:
|
|
74
|
+
"""判断缓存是否已满。
|
|
75
|
+
|
|
76
|
+
:return: 缓存已满返回True,否则返回False
|
|
77
|
+
"""
|
|
78
|
+
return len(self._cache) >= self._capacity
|
|
79
|
+
|
|
80
|
+
def keys(self) -> KeysView:
|
|
81
|
+
"""获取所有缓存键,按使用顺序排列。
|
|
82
|
+
|
|
83
|
+
:return: 缓存键的视图(从最久未使用到最近使用)
|
|
84
|
+
"""
|
|
85
|
+
return self._cache.keys()
|
|
86
|
+
|
|
87
|
+
def __contains__(self, key: Any) -> bool:
|
|
88
|
+
"""判断键是否存在于缓存中。"""
|
|
89
|
+
return key in self._cache
|
|
90
|
+
|
|
91
|
+
def __len__(self) -> int:
|
|
92
|
+
"""返回缓存大小。"""
|
|
93
|
+
return len(self._cache)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TimedCache:
|
|
7
|
+
"""定时缓存实现。
|
|
8
|
+
|
|
9
|
+
每个缓存条目可以设置独立的过期时间,过期后自动失效。
|
|
10
|
+
支持定时清理过期条目以释放内存。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def __init__(self, timeout: int = 60) -> None:
|
|
14
|
+
"""初始化定时缓存。
|
|
15
|
+
|
|
16
|
+
:param timeout: 默认过期时间(秒),默认60秒
|
|
17
|
+
"""
|
|
18
|
+
self._timeout: int = timeout
|
|
19
|
+
self._cache: dict = {} # key -> (value, expire_time)
|
|
20
|
+
self._lock: threading.Lock = threading.Lock()
|
|
21
|
+
self._prune_timer: Optional[threading.Timer] = None
|
|
22
|
+
|
|
23
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
24
|
+
"""获取缓存值。若已过期则返回默认值。
|
|
25
|
+
|
|
26
|
+
:param key: 缓存键
|
|
27
|
+
:param default: 键不存在或已过期时返回的默认值
|
|
28
|
+
:return: 缓存值,不存在或已过期时返回默认值
|
|
29
|
+
"""
|
|
30
|
+
with self._lock:
|
|
31
|
+
if key not in self._cache:
|
|
32
|
+
return default
|
|
33
|
+
value, expire_time = self._cache[key]
|
|
34
|
+
if time.time() > expire_time:
|
|
35
|
+
del self._cache[key]
|
|
36
|
+
return default
|
|
37
|
+
return value
|
|
38
|
+
|
|
39
|
+
def put(self, key: Any, value: Any, timeout: Optional[int] = None) -> None:
|
|
40
|
+
"""放入缓存。
|
|
41
|
+
|
|
42
|
+
:param key: 缓存键
|
|
43
|
+
:param value: 缓存值
|
|
44
|
+
:param timeout: 过期时间(秒),为None时使用默认过期时间
|
|
45
|
+
"""
|
|
46
|
+
expire_time = time.time() + (timeout if timeout is not None else self._timeout)
|
|
47
|
+
with self._lock:
|
|
48
|
+
self._cache[key] = (value, expire_time)
|
|
49
|
+
|
|
50
|
+
def remove(self, key: Any) -> Any:
|
|
51
|
+
"""移除指定键的缓存。
|
|
52
|
+
|
|
53
|
+
:param key: 缓存键
|
|
54
|
+
:return: 被移除的值,键不存在时返回None
|
|
55
|
+
"""
|
|
56
|
+
with self._lock:
|
|
57
|
+
entry = self._cache.pop(key, None)
|
|
58
|
+
if entry is None:
|
|
59
|
+
return None
|
|
60
|
+
value, _ = entry
|
|
61
|
+
return value
|
|
62
|
+
|
|
63
|
+
def size(self) -> int:
|
|
64
|
+
"""获取当前缓存大小(包含已过期但未清理的条目)。
|
|
65
|
+
|
|
66
|
+
:return: 当前缓存条目数
|
|
67
|
+
"""
|
|
68
|
+
with self._lock:
|
|
69
|
+
return len(self._cache)
|
|
70
|
+
|
|
71
|
+
def clear(self) -> None:
|
|
72
|
+
"""清空所有缓存。"""
|
|
73
|
+
with self._lock:
|
|
74
|
+
self._cache.clear()
|
|
75
|
+
|
|
76
|
+
def prune(self) -> int:
|
|
77
|
+
"""清理过期缓存条目。
|
|
78
|
+
|
|
79
|
+
:return: 被清理的条目数
|
|
80
|
+
"""
|
|
81
|
+
now = time.time()
|
|
82
|
+
expired_keys: list = []
|
|
83
|
+
with self._lock:
|
|
84
|
+
for key, (_, expire_time) in self._cache.items():
|
|
85
|
+
if now > expire_time:
|
|
86
|
+
expired_keys.append(key)
|
|
87
|
+
for key in expired_keys:
|
|
88
|
+
del self._cache[key]
|
|
89
|
+
return len(expired_keys)
|
|
90
|
+
|
|
91
|
+
def schedule_prune(self, delay_seconds: int = 60) -> None:
|
|
92
|
+
"""启动定时清理线程,定期清理过期缓存。
|
|
93
|
+
|
|
94
|
+
:param delay_seconds: 清理间隔(秒),默认60秒
|
|
95
|
+
"""
|
|
96
|
+
self._cancel_prune_timer()
|
|
97
|
+
self._prune_timer = threading.Timer(delay_seconds, self._prune_callback, args=(delay_seconds,))
|
|
98
|
+
self._prune_timer.daemon = True
|
|
99
|
+
self._prune_timer.start()
|
|
100
|
+
|
|
101
|
+
def _prune_callback(self, delay_seconds: int) -> None:
|
|
102
|
+
"""清理回调,执行清理后重新调度。
|
|
103
|
+
|
|
104
|
+
:param delay_seconds: 下次清理间隔(秒)
|
|
105
|
+
"""
|
|
106
|
+
self.prune()
|
|
107
|
+
self._prune_timer = threading.Timer(delay_seconds, self._prune_callback, args=(delay_seconds,))
|
|
108
|
+
self._prune_timer.daemon = True
|
|
109
|
+
self._prune_timer.start()
|
|
110
|
+
|
|
111
|
+
def _cancel_prune_timer(self) -> None:
|
|
112
|
+
"""取消定时清理线程。"""
|
|
113
|
+
if self._prune_timer is not None:
|
|
114
|
+
self._prune_timer.cancel()
|
|
115
|
+
self._prune_timer = None
|