ErisPulse 1.1.13__py3-none-any.whl → 1.1.14__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.
- ErisPulse/__init__.py +201 -112
- ErisPulse/__main__.py +51 -2
- ErisPulse/adapter.py +351 -0
- ErisPulse/db.py +689 -8
- ErisPulse/logger.py +325 -1
- ErisPulse/mods.py +331 -0
- ErisPulse/raiserr.py +159 -1
- ErisPulse/util.py +421 -0
- erispulse-1.1.14.dist-info/METADATA +165 -0
- erispulse-1.1.14.dist-info/RECORD +13 -0
- {erispulse-1.1.13.dist-info → erispulse-1.1.14.dist-info}/WHEEL +1 -2
- erispulse-1.1.13.dist-info/METADATA +0 -79
- erispulse-1.1.13.dist-info/RECORD +0 -14
- erispulse-1.1.13.dist-info/top_level.txt +0 -1
- {erispulse-1.1.13.dist-info → erispulse-1.1.14.dist-info}/entry_points.txt +0 -0
- {erispulse-1.1.13.dist-info → erispulse-1.1.14.dist-info}/licenses/LICENSE +0 -0
ErisPulse/raiserr.py
CHANGED
|
@@ -1,3 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# 错误管理系统
|
|
3
|
+
|
|
4
|
+
提供错误类型注册、抛出和管理功能,集成全局异常处理。支持自定义错误类型、错误链追踪和全局异常捕获。
|
|
5
|
+
|
|
6
|
+
## 核心功能
|
|
7
|
+
1. 错误类型注册和管理
|
|
8
|
+
2. 动态错误抛出
|
|
9
|
+
3. 全局异常处理
|
|
10
|
+
4. 错误信息追踪
|
|
11
|
+
5. 异步错误处理
|
|
12
|
+
|
|
13
|
+
## API 文档
|
|
14
|
+
|
|
15
|
+
### 错误注册
|
|
16
|
+
#### register(name: str, doc: str = "", base: type = Exception) -> type
|
|
17
|
+
注册新的错误类型。
|
|
18
|
+
- 参数:
|
|
19
|
+
- name: 错误类型名称
|
|
20
|
+
- doc: 错误描述文档
|
|
21
|
+
- base: 基础异常类,默认为Exception
|
|
22
|
+
- 返回:
|
|
23
|
+
- type: 注册的错误类型类
|
|
24
|
+
- 示例:
|
|
25
|
+
```python
|
|
26
|
+
# 注册一个简单错误
|
|
27
|
+
sdk.raiserr.register("SimpleError", "简单的错误类型")
|
|
28
|
+
|
|
29
|
+
# 注册带有自定义基类的错误
|
|
30
|
+
class CustomBase(Exception):
|
|
31
|
+
pass
|
|
32
|
+
sdk.raiserr.register("AdvancedError", "高级错误", CustomBase)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### info(name: str = None) -> dict | None
|
|
36
|
+
获取错误类型信息。
|
|
37
|
+
- 参数:
|
|
38
|
+
- name: 错误类型名称,如果为None则返回所有错误类型信息
|
|
39
|
+
- 返回:
|
|
40
|
+
- dict: 包含错误类型信息的字典,包括类型名、文档和类引用
|
|
41
|
+
- None: 如果指定的错误类型不存在
|
|
42
|
+
- 示例:
|
|
43
|
+
```python
|
|
44
|
+
# 获取特定错误信息
|
|
45
|
+
error_info = sdk.raiserr.info("SimpleError")
|
|
46
|
+
print(f"错误类型: {error_info['type']}")
|
|
47
|
+
print(f"错误描述: {error_info['doc']}")
|
|
48
|
+
|
|
49
|
+
# 获取所有注册的错误信息
|
|
50
|
+
all_errors = sdk.raiserr.info()
|
|
51
|
+
for name, info in all_errors.items():
|
|
52
|
+
print(f"{name}: {info['doc']}")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 错误抛出
|
|
56
|
+
#### ErrorType(msg: str, exit: bool = False)
|
|
57
|
+
动态生成的错误抛出函数。
|
|
58
|
+
- 参数:
|
|
59
|
+
- msg: 错误消息
|
|
60
|
+
- exit: 是否在抛出错误后退出程序
|
|
61
|
+
- 示例:
|
|
62
|
+
```python
|
|
63
|
+
# 抛出不退出的错误
|
|
64
|
+
sdk.raiserr.SimpleError("操作失败")
|
|
65
|
+
|
|
66
|
+
# 抛出导致程序退出的错误
|
|
67
|
+
sdk.raiserr.CriticalError("致命错误", exit=True)
|
|
68
|
+
|
|
69
|
+
# 带有异常捕获的使用方式
|
|
70
|
+
try:
|
|
71
|
+
sdk.raiserr.ValidationError("数据验证失败")
|
|
72
|
+
except Exception as e:
|
|
73
|
+
print(f"捕获到错误: {e}")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 全局异常处理
|
|
77
|
+
#### global_exception_handler(exc_type: type, exc_value: Exception, exc_traceback: traceback)
|
|
78
|
+
全局同步异常处理器。
|
|
79
|
+
- 参数:
|
|
80
|
+
- exc_type: 异常类型
|
|
81
|
+
- exc_value: 异常值
|
|
82
|
+
- exc_traceback: 异常追踪信息
|
|
83
|
+
- 示例:
|
|
84
|
+
```python
|
|
85
|
+
# 系统会自动捕获未处理的异常
|
|
86
|
+
def risky_operation():
|
|
87
|
+
raise Exception("未处理的异常")
|
|
88
|
+
|
|
89
|
+
# 异常会被global_exception_handler捕获并处理
|
|
90
|
+
risky_operation()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### async_exception_handler(loop: asyncio.AbstractEventLoop, context: dict)
|
|
94
|
+
全局异步异常处理器。
|
|
95
|
+
- 参数:
|
|
96
|
+
- loop: 事件循环实例
|
|
97
|
+
- context: 异常上下文信息
|
|
98
|
+
- 示例:
|
|
99
|
+
```python
|
|
100
|
+
async def async_operation():
|
|
101
|
+
raise Exception("异步操作错误")
|
|
102
|
+
|
|
103
|
+
# 异常会被async_exception_handler捕获并处理
|
|
104
|
+
asyncio.create_task(async_operation())
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 最佳实践
|
|
108
|
+
1. 错误类型注册
|
|
109
|
+
```python
|
|
110
|
+
# 为特定功能模块注册错误类型
|
|
111
|
+
sdk.raiserr.register("DatabaseError", "数据库操作错误")
|
|
112
|
+
sdk.raiserr.register("NetworkError", "网络连接错误")
|
|
113
|
+
sdk.raiserr.register("ValidationError", "数据验证错误")
|
|
114
|
+
|
|
115
|
+
# 使用继承关系组织错误类型
|
|
116
|
+
class ModuleError(Exception):
|
|
117
|
+
pass
|
|
118
|
+
sdk.raiserr.register("ConfigError", "配置错误", ModuleError)
|
|
119
|
+
sdk.raiserr.register("PluginError", "插件错误", ModuleError)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
2. 错误处理流程
|
|
123
|
+
```python
|
|
124
|
+
def process_data(data):
|
|
125
|
+
try:
|
|
126
|
+
if not data:
|
|
127
|
+
sdk.raiserr.ValidationError("数据不能为空")
|
|
128
|
+
if not isinstance(data, dict):
|
|
129
|
+
sdk.raiserr.ValidationError("数据必须是字典类型")
|
|
130
|
+
|
|
131
|
+
# 处理数据...
|
|
132
|
+
|
|
133
|
+
except Exception as e:
|
|
134
|
+
# 错误会被自动记录并处理
|
|
135
|
+
sdk.raiserr.ProcessingError(f"数据处理失败: {str(e)}")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
3. 异步环境使用
|
|
139
|
+
```python
|
|
140
|
+
async def async_task():
|
|
141
|
+
try:
|
|
142
|
+
result = await some_async_operation()
|
|
143
|
+
if not result.success:
|
|
144
|
+
sdk.raiserr.AsyncOperationError("异步操作失败")
|
|
145
|
+
except Exception as e:
|
|
146
|
+
# 异步错误会被async_exception_handler捕获
|
|
147
|
+
raise
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 注意事项
|
|
151
|
+
1. 错误类型命名应具有描述性,便于理解错误来源
|
|
152
|
+
2. 错误消息应包含足够的上下文信息,便于调试
|
|
153
|
+
3. 适当使用exit参数,只在致命错误时设置为True
|
|
154
|
+
4. 避免在全局异常处理器中执行耗时操作
|
|
155
|
+
5. 确保异步代码中的错误能够被正确捕获和处理
|
|
156
|
+
|
|
157
|
+
"""
|
|
158
|
+
|
|
1
159
|
import sys
|
|
2
160
|
import traceback
|
|
3
161
|
import asyncio
|
|
@@ -71,4 +229,4 @@ def async_exception_handler(loop, context):
|
|
|
71
229
|
)
|
|
72
230
|
else:
|
|
73
231
|
logger.warning(f"异步任务警告: {message}")
|
|
74
|
-
asyncio.get_event_loop().set_exception_handler(async_exception_handler)
|
|
232
|
+
asyncio.get_event_loop().set_exception_handler(async_exception_handler)
|
ErisPulse/util.py
CHANGED
|
@@ -1,7 +1,379 @@
|
|
|
1
|
+
"""
|
|
2
|
+
# 工具函数集合
|
|
3
|
+
|
|
4
|
+
提供各种实用工具函数和装饰器,简化开发流程。包括依赖关系处理、性能优化、异步执行和错误重试等功能。
|
|
5
|
+
|
|
6
|
+
## 核心功能
|
|
7
|
+
1. 依赖关系管理
|
|
8
|
+
2. 函数结果缓存
|
|
9
|
+
3. 异步执行支持
|
|
10
|
+
4. 自动重试机制
|
|
11
|
+
5. 可视化工具
|
|
12
|
+
6. 版本管理和比较
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## API 文档
|
|
16
|
+
|
|
17
|
+
### 依赖关系处理
|
|
18
|
+
#### topological_sort(elements: list, dependencies: dict, error: callable) -> list
|
|
19
|
+
对元素进行拓扑排序,解析依赖关系。
|
|
20
|
+
- 参数:
|
|
21
|
+
- elements: 需要排序的元素列表
|
|
22
|
+
- dependencies: 依赖关系字典,键为元素,值为该元素依赖的元素列表
|
|
23
|
+
- error: 发生循环依赖时调用的错误处理函数
|
|
24
|
+
- 返回:
|
|
25
|
+
- list: 排序后的元素列表
|
|
26
|
+
- 异常:
|
|
27
|
+
- 当存在循环依赖时,调用error函数
|
|
28
|
+
- 示例:
|
|
29
|
+
```python
|
|
30
|
+
# 基本使用
|
|
31
|
+
modules = ["ModuleA", "ModuleB", "ModuleC"]
|
|
32
|
+
dependencies = {
|
|
33
|
+
"ModuleB": ["ModuleA"],
|
|
34
|
+
"ModuleC": ["ModuleB"]
|
|
35
|
+
}
|
|
36
|
+
sorted_modules = sdk.util.topological_sort(modules, dependencies, sdk.raiserr.CycleDependencyError)
|
|
37
|
+
|
|
38
|
+
# 复杂依赖处理
|
|
39
|
+
modules = ["Database", "Cache", "API", "UI"]
|
|
40
|
+
dependencies = {
|
|
41
|
+
"Cache": ["Database"],
|
|
42
|
+
"API": ["Database", "Cache"],
|
|
43
|
+
"UI": ["API"]
|
|
44
|
+
}
|
|
45
|
+
try:
|
|
46
|
+
sorted_modules = sdk.util.topological_sort(
|
|
47
|
+
modules,
|
|
48
|
+
dependencies,
|
|
49
|
+
sdk.raiserr.CycleDependencyError
|
|
50
|
+
)
|
|
51
|
+
print("加载顺序:", sorted_modules)
|
|
52
|
+
except Exception as e:
|
|
53
|
+
print(f"依赖解析失败: {e}")
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### show_topology() -> str
|
|
57
|
+
可视化显示当前模块的依赖关系。
|
|
58
|
+
- 参数: 无
|
|
59
|
+
- 返回:
|
|
60
|
+
- str: 格式化的依赖关系树文本
|
|
61
|
+
- 示例:
|
|
62
|
+
```python
|
|
63
|
+
# 显示所有模块依赖
|
|
64
|
+
topology = sdk.util.show_topology()
|
|
65
|
+
print(topology)
|
|
66
|
+
|
|
67
|
+
# 在日志中记录依赖关系
|
|
68
|
+
sdk.logger.info("模块依赖关系:\n" + sdk.util.show_topology())
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 性能优化装饰器
|
|
72
|
+
#### @cache
|
|
73
|
+
缓存函数调用结果的装饰器。
|
|
74
|
+
- 参数: 无
|
|
75
|
+
- 返回:
|
|
76
|
+
- function: 被装饰的函数
|
|
77
|
+
- 示例:
|
|
78
|
+
```python
|
|
79
|
+
# 缓存计算密集型函数结果
|
|
80
|
+
@sdk.util.cache
|
|
81
|
+
def calculate_complex_data(param1: int, param2: str) -> dict:
|
|
82
|
+
# 复杂计算...
|
|
83
|
+
return result
|
|
84
|
+
|
|
85
|
+
# 缓存配置读取
|
|
86
|
+
@sdk.util.cache
|
|
87
|
+
def get_config(config_name: str) -> dict:
|
|
88
|
+
return load_config_from_file(config_name)
|
|
89
|
+
|
|
90
|
+
# 带有可变参数的缓存
|
|
91
|
+
@sdk.util.cache
|
|
92
|
+
def process_data(*args, **kwargs) -> Any:
|
|
93
|
+
return complex_processing(args, kwargs)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 异步执行工具
|
|
97
|
+
#### @run_in_executor
|
|
98
|
+
将同步函数转换为异步执行的装饰器。
|
|
99
|
+
- 参数: 无
|
|
100
|
+
- 返回:
|
|
101
|
+
- function: 异步包装的函数
|
|
102
|
+
- 示例:
|
|
103
|
+
```python
|
|
104
|
+
# 包装同步IO操作
|
|
105
|
+
@sdk.util.run_in_executor
|
|
106
|
+
def read_large_file(file_path: str) -> str:
|
|
107
|
+
with open(file_path, 'r') as f:
|
|
108
|
+
return f.read()
|
|
109
|
+
|
|
110
|
+
# 包装CPU密集型操作
|
|
111
|
+
@sdk.util.run_in_executor
|
|
112
|
+
def process_image(image_data: bytes) -> bytes:
|
|
113
|
+
# 图像处理...
|
|
114
|
+
return processed_data
|
|
115
|
+
|
|
116
|
+
# 在异步环境中使用
|
|
117
|
+
async def main():
|
|
118
|
+
# 这些操作会在线程池中执行,不会阻塞事件循环
|
|
119
|
+
file_content = await read_large_file("large_file.txt")
|
|
120
|
+
processed_image = await process_image(image_data)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### ExecAsync(async_func: Callable, *args, **kwargs) -> Any
|
|
124
|
+
在当前线程中执行异步函数。
|
|
125
|
+
- 参数:
|
|
126
|
+
- async_func: 要执行的异步函数
|
|
127
|
+
- *args: 传递给异步函数的位置参数
|
|
128
|
+
- **kwargs: 传递给异步函数的关键字参数
|
|
129
|
+
- 返回:
|
|
130
|
+
- Any: 异步函数的执行结果
|
|
131
|
+
- 示例:
|
|
132
|
+
```python
|
|
133
|
+
# 在同步环境中执行异步函数
|
|
134
|
+
async def fetch_data(url: str) -> dict:
|
|
135
|
+
async with aiohttp.ClientSession() as session:
|
|
136
|
+
async with session.get(url) as response:
|
|
137
|
+
return await response.json()
|
|
138
|
+
|
|
139
|
+
# 同步环境中调用
|
|
140
|
+
result = sdk.util.ExecAsync(fetch_data, "https://api.example.com/data")
|
|
141
|
+
|
|
142
|
+
# 批量异步操作
|
|
143
|
+
async def process_multiple(items: list) -> list:
|
|
144
|
+
results = []
|
|
145
|
+
for item in items:
|
|
146
|
+
result = await process_item(item)
|
|
147
|
+
results.append(result)
|
|
148
|
+
return results
|
|
149
|
+
|
|
150
|
+
# 在同步代码中执行
|
|
151
|
+
results = sdk.util.ExecAsync(process_multiple, items_list)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 错误重试机制
|
|
155
|
+
#### @retry(max_attempts: int = 3, delay: int = 1)
|
|
156
|
+
为不稳定的操作添加自动重试机制的装饰器。
|
|
157
|
+
- 参数:
|
|
158
|
+
- max_attempts: 最大重试次数,默认3次
|
|
159
|
+
- delay: 重试间隔时间(秒),默认1秒
|
|
160
|
+
- 返回:
|
|
161
|
+
- function: 包装了重试逻辑的函数
|
|
162
|
+
- 示例:
|
|
163
|
+
```python
|
|
164
|
+
# 基本重试
|
|
165
|
+
@sdk.util.retry()
|
|
166
|
+
def unstable_network_call() -> dict:
|
|
167
|
+
return requests.get("https://api.example.com/data").json()
|
|
168
|
+
|
|
169
|
+
# 自定义重试参数
|
|
170
|
+
@sdk.util.retry(max_attempts=5, delay=2)
|
|
171
|
+
def connect_database() -> Connection:
|
|
172
|
+
return create_database_connection()
|
|
173
|
+
|
|
174
|
+
# 带有条件的重试
|
|
175
|
+
@sdk.util.retry(max_attempts=3)
|
|
176
|
+
def process_with_retry(data: dict) -> bool:
|
|
177
|
+
if not validate_data(data):
|
|
178
|
+
raise ValueError("Invalid data")
|
|
179
|
+
return process_data(data)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### 版本管理工具
|
|
183
|
+
#### parse_dependency_with_version(dependency_str: str) -> tuple
|
|
184
|
+
解析带有版本要求的依赖字符串。
|
|
185
|
+
- 参数:
|
|
186
|
+
- dependency_str: 依赖字符串,如 "ModuleA==1.0.0", "ModuleB>=2.0.0"
|
|
187
|
+
- 返回:
|
|
188
|
+
- tuple: (模块名, 操作符, 版本号) 或 (模块名, None, None)
|
|
189
|
+
- 示例:
|
|
190
|
+
```python
|
|
191
|
+
# 解析带版本要求的依赖
|
|
192
|
+
module_name, operator, version = sdk.util.parse_dependency_with_version("ModuleA==1.0.0")
|
|
193
|
+
print(f"模块: {module_name}, 操作符: {operator}, 版本: {version}")
|
|
194
|
+
# 输出: 模块: ModuleA, 操作符: ==, 版本: 1.0.0
|
|
195
|
+
|
|
196
|
+
# 解析不带版本要求的依赖
|
|
197
|
+
module_name, operator, version = sdk.util.parse_dependency_with_version("ModuleB")
|
|
198
|
+
print(f"模块: {module_name}, 操作符: {operator}, 版本: {version}")
|
|
199
|
+
# 输出: 模块: ModuleB, 操作符: None, 版本: None
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### compare_versions(version1: str, version2: str) -> int
|
|
203
|
+
比较两个版本号。
|
|
204
|
+
- 参数:
|
|
205
|
+
- version1: 第一个版本号字符串,如 "1.0.0"
|
|
206
|
+
- version2: 第二个版本号字符串,如 "2.0.0"
|
|
207
|
+
- 返回:
|
|
208
|
+
- int: 如果 version1 < version2 返回 -1,如果 version1 == version2 返回 0,如果 version1 > version2 返回 1
|
|
209
|
+
- 示例:
|
|
210
|
+
```python
|
|
211
|
+
# 比较版本号
|
|
212
|
+
result = sdk.util.compare_versions("1.0.0", "2.0.0")
|
|
213
|
+
print(f"比较结果: {result}") # 输出: 比较结果: -1
|
|
214
|
+
|
|
215
|
+
result = sdk.util.compare_versions("2.0.0", "2.0.0")
|
|
216
|
+
print(f"比较结果: {result}") # 输出: 比较结果: 0
|
|
217
|
+
|
|
218
|
+
result = sdk.util.compare_versions("2.1.0", "2.0.5")
|
|
219
|
+
print(f"比较结果: {result}") # 输出: 比较结果: 1
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
#### check_version_requirement(current_version: str, operator: str, required_version: str) -> bool
|
|
223
|
+
检查当前版本是否满足版本要求。
|
|
224
|
+
- 参数:
|
|
225
|
+
- current_version: 当前版本号字符串,如 "1.0.0"
|
|
226
|
+
- operator: 操作符,如 "==", ">=", "<="
|
|
227
|
+
- required_version: 要求的版本号字符串,如 "2.0.0"
|
|
228
|
+
- 返回:
|
|
229
|
+
- bool: 如果满足要求返回 True,否则返回 False
|
|
230
|
+
- 示例:
|
|
231
|
+
```python
|
|
232
|
+
# 检查版本要求
|
|
233
|
+
result = sdk.util.check_version_requirement("1.0.0", "==", "1.0.0")
|
|
234
|
+
print(f"版本匹配: {result}") # 输出: 版本匹配: True
|
|
235
|
+
|
|
236
|
+
result = sdk.util.check_version_requirement("1.5.0", ">=", "1.0.0")
|
|
237
|
+
print(f"版本匹配: {result}") # 输出: 版本匹配: True
|
|
238
|
+
|
|
239
|
+
result = sdk.util.check_version_requirement("2.0.0", "<", "1.0.0")
|
|
240
|
+
print(f"版本匹配: {result}") # 输出: 版本匹配: False
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## 最佳实践
|
|
244
|
+
1. 依赖管理
|
|
245
|
+
```python
|
|
246
|
+
# 模块依赖定义
|
|
247
|
+
module_deps = {
|
|
248
|
+
"core": [],
|
|
249
|
+
"database": ["core"],
|
|
250
|
+
"api": ["database"],
|
|
251
|
+
"ui": ["api"]
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# 验证并排序依赖
|
|
255
|
+
try:
|
|
256
|
+
load_order = sdk.util.topological_sort(
|
|
257
|
+
list(module_deps.keys()),
|
|
258
|
+
module_deps,
|
|
259
|
+
sdk.raiserr.CycleDependencyError
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# 按顺序加载模块
|
|
263
|
+
for module in load_order:
|
|
264
|
+
load_module(module)
|
|
265
|
+
except Exception as e:
|
|
266
|
+
sdk.logger.error(f"模块加载失败: {e}")
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
2. 性能优化
|
|
270
|
+
```python
|
|
271
|
+
# 合理使用缓存
|
|
272
|
+
@sdk.util.cache
|
|
273
|
+
def get_user_preferences(user_id: str) -> dict:
|
|
274
|
+
return database.fetch_user_preferences(user_id)
|
|
275
|
+
|
|
276
|
+
# 异步处理耗时操作
|
|
277
|
+
@sdk.util.run_in_executor
|
|
278
|
+
def process_large_dataset(data: list) -> list:
|
|
279
|
+
return [complex_calculation(item) for item in data]
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
3. 错误处理和重试
|
|
283
|
+
```python
|
|
284
|
+
# 组合使用重试和异步
|
|
285
|
+
@sdk.util.retry(max_attempts=3, delay=2)
|
|
286
|
+
@sdk.util.run_in_executor
|
|
287
|
+
def reliable_network_operation():
|
|
288
|
+
response = requests.get("https://api.example.com")
|
|
289
|
+
response.raise_for_status()
|
|
290
|
+
return response.json()
|
|
291
|
+
|
|
292
|
+
# 带有自定义错误处理的重试
|
|
293
|
+
@sdk.util.retry(max_attempts=5)
|
|
294
|
+
def safe_operation():
|
|
295
|
+
try:
|
|
296
|
+
return perform_risky_operation()
|
|
297
|
+
except Exception as e:
|
|
298
|
+
sdk.logger.warning(f"操作失败,准备重试: {e}")
|
|
299
|
+
raise
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
4. 版本管理
|
|
303
|
+
```python
|
|
304
|
+
# 在模块中定义依赖
|
|
305
|
+
moduleInfo = {
|
|
306
|
+
"meta": {
|
|
307
|
+
"name": "AdvancedFeatures",
|
|
308
|
+
"version": "1.2.0"
|
|
309
|
+
},
|
|
310
|
+
"dependencies": {
|
|
311
|
+
"requires": [
|
|
312
|
+
"CoreModule>=1.0.0",
|
|
313
|
+
"DatabaseModule==2.1.0"
|
|
314
|
+
],
|
|
315
|
+
"optional": [
|
|
316
|
+
"VisualizationModule>=1.5.0",
|
|
317
|
+
["CacheModule>2.0.0", "FastCacheModule>=1.0.0"]
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
# 手动检查版本兼容性
|
|
323
|
+
def check_plugin_compatibility(plugin_info):
|
|
324
|
+
required_version = "2.0.0"
|
|
325
|
+
plugin_version = plugin_info.get("version", "0.0.0")
|
|
326
|
+
|
|
327
|
+
if sdk.util.check_version_requirement(plugin_version, ">=", required_version):
|
|
328
|
+
sdk.logger.info(f"插件 '{plugin_info['name']}' 版本兼容")
|
|
329
|
+
return True
|
|
330
|
+
else:
|
|
331
|
+
sdk.logger.warning(f"插件 '{plugin_info['name']}' 版本 {plugin_version} 不兼容,需要 >={required_version}")
|
|
332
|
+
return False
|
|
333
|
+
|
|
334
|
+
# 解析带版本要求的依赖字符串
|
|
335
|
+
def process_dependency(dependency_str):
|
|
336
|
+
module_name, operator, version = sdk.util.parse_dependency_with_version(dependency_str)
|
|
337
|
+
if operator and version:
|
|
338
|
+
return f"需要模块 {module_name} {operator}{version}"
|
|
339
|
+
else:
|
|
340
|
+
return f"需要模块 {module_name},无版本要求"
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## 注意事项
|
|
344
|
+
1. 缓存使用
|
|
345
|
+
- 注意内存占用,避免缓存过大数据
|
|
346
|
+
- 考虑缓存失效策略
|
|
347
|
+
- 不要缓存频繁变化的数据
|
|
348
|
+
|
|
349
|
+
2. 异步执行
|
|
350
|
+
- 避免在 run_in_executor 中执行过长的操作
|
|
351
|
+
- 注意异常处理和资源清理
|
|
352
|
+
- 合理使用线程池
|
|
353
|
+
|
|
354
|
+
3. 重试机制
|
|
355
|
+
- 设置合适的重试次数和间隔
|
|
356
|
+
- 只对可重试的操作使用重试装饰器
|
|
357
|
+
- 注意避免重试导致的资源浪费
|
|
358
|
+
|
|
359
|
+
4. 依赖管理
|
|
360
|
+
- 保持依赖关系清晰简单
|
|
361
|
+
- 避免循环依赖
|
|
362
|
+
- 定期检查和更新依赖关系
|
|
363
|
+
|
|
364
|
+
5. 版本管理
|
|
365
|
+
- 遵循语义化版本规范(主版本.次版本.修订版本)
|
|
366
|
+
- 明确指定版本要求,避免使用过于宽松的版本约束
|
|
367
|
+
- 在主版本更新时,注意可能的不兼容变更
|
|
368
|
+
- 测试不同版本依赖组合的兼容性
|
|
369
|
+
- 为模块提供明确的版本号和更新日志
|
|
370
|
+
"""
|
|
371
|
+
|
|
1
372
|
import time
|
|
2
373
|
import asyncio
|
|
3
374
|
import functools
|
|
4
375
|
import traceback
|
|
376
|
+
import re
|
|
5
377
|
from concurrent.futures import ThreadPoolExecutor
|
|
6
378
|
from collections import defaultdict, deque
|
|
7
379
|
|
|
@@ -97,3 +469,52 @@ def retry(max_attempts=3, delay=1):
|
|
|
97
469
|
time.sleep(delay)
|
|
98
470
|
return wrapper
|
|
99
471
|
return decorator
|
|
472
|
+
|
|
473
|
+
def parse_dependency_with_version(dependency_str):
|
|
474
|
+
pattern = r'^([a-zA-Z0-9_\-]+)(?:([=<>!]+)([0-9]+(?:\.[0-9]+)*))?\s**$'
|
|
475
|
+
match = re.match(pattern, dependency_str)
|
|
476
|
+
|
|
477
|
+
if not match:
|
|
478
|
+
return dependency_str, None, None
|
|
479
|
+
|
|
480
|
+
module_name, operator, version = match.groups()
|
|
481
|
+
return module_name, operator, version
|
|
482
|
+
|
|
483
|
+
def compare_versions(version1, version2):
|
|
484
|
+
v1_parts = [int(x) for x in version1.split('.')]
|
|
485
|
+
v2_parts = [int(x) for x in version2.split('.')]
|
|
486
|
+
|
|
487
|
+
# 确保两个版本号有相同的部分数
|
|
488
|
+
while len(v1_parts) < len(v2_parts):
|
|
489
|
+
v1_parts.append(0)
|
|
490
|
+
while len(v2_parts) < len(v1_parts):
|
|
491
|
+
v2_parts.append(0)
|
|
492
|
+
|
|
493
|
+
for i in range(len(v1_parts)):
|
|
494
|
+
if v1_parts[i] < v2_parts[i]:
|
|
495
|
+
return -1
|
|
496
|
+
elif v1_parts[i] > v2_parts[i]:
|
|
497
|
+
return 1
|
|
498
|
+
|
|
499
|
+
return 0
|
|
500
|
+
|
|
501
|
+
def check_version_requirement(current_version, operator, required_version):
|
|
502
|
+
if not operator or not required_version:
|
|
503
|
+
return True
|
|
504
|
+
|
|
505
|
+
comparison = compare_versions(current_version, required_version)
|
|
506
|
+
|
|
507
|
+
if operator == '==':
|
|
508
|
+
return comparison == 0
|
|
509
|
+
elif operator == '!=':
|
|
510
|
+
return comparison != 0
|
|
511
|
+
elif operator == '>':
|
|
512
|
+
return comparison > 0
|
|
513
|
+
elif operator == '>=':
|
|
514
|
+
return comparison >= 0
|
|
515
|
+
elif operator == '<':
|
|
516
|
+
return comparison < 0
|
|
517
|
+
elif operator == '<=':
|
|
518
|
+
return comparison <= 0
|
|
519
|
+
|
|
520
|
+
return False
|