oafuncs 0.0.98.3__py3-none-any.whl → 0.0.98.5__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.
oafuncs/oa_tool.py CHANGED
@@ -1,50 +1,120 @@
1
- from typing import Any, Iterable, List, Optional, Union
1
+ import datetime
2
+ import logging
3
+ from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
2
4
 
3
5
  from rich import print
4
6
 
7
+ from ._script.parallel import ParallelExecutor
8
+
5
9
  __all__ = ["PEx", "email", "pbar"]
6
10
 
7
11
 
8
- class PEx:
12
+ class PEx(ParallelExecutor):
9
13
  """
10
- PEx wraps ParallelExecutor and delegates all its methods,
11
- allowing direct calls to PEx methods to achieve the same effect as ParallelExecutor.
14
+ 并行执行器扩展类 (ParallelExecutor Extend)
12
15
 
13
- Example:
14
- # Create a PEx instance
15
- executor = PEx(max_workers=4)
16
+ 继承自 ParallelExecutor,提供更简洁的接口和增强功能:
16
17
 
17
- # Use the run method to execute parallel tasks
18
- result = executor.run(lambda x: x * x, [(i,) for i in range(5)])
19
- print(result) # Output: [0, 1, 4, 9, 16]
20
- """
18
+ 特点:
19
+ - 自动时间统计 (开始/结束时间、总耗时)
20
+ - 增强的错误处理机制
21
+ - 友好的统计输出格式
22
+ - 支持进度回调函数
21
23
 
22
- try:
23
- from ._script.parallel import ParallelExecutor
24
- except ImportError:
25
- raise ImportError("[red]ParallelExecutor could not be imported. Ensure the module '_script.parallel' exists and is accessible.[/red]")
24
+ 示例:
25
+ >>> with PEx() as executor:
26
+ ... results = executor.run(lambda x: x*2, [(i,) for i in range(5)])
27
+ ... print(executor.format_stats())
28
+ [2024-06-08 15:30:00] 成功处理5个任务 (耗时0.5秒)
26
29
 
27
- def __init__(self, *args: Any, **kwargs: Any) -> None:
30
+ 参数调整建议:
31
+ - 内存密集型任务:增大 mem_per_process
32
+ - I/O密集型任务:使用 mode='thread'
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ max_workers: Optional[int] = None,
38
+ chunk_size: Optional[int] = None,
39
+ mem_per_process: float = 1.5, # 调大默认内存限制
40
+ timeout_per_task: int = 7200, # 延长默认超时时间
41
+ max_retries: int = 5, # 增加默认重试次数
42
+ progress_callback: Optional[Callable[[int, int], None]] = None,
43
+ ):
44
+ """
45
+ 初始化并行执行器
46
+
47
+ :param max_workers: 最大工作进程/线程数 (默认自动计算)
48
+ :param chunk_size: 任务分块大小 (默认自动优化)
49
+ :param mem_per_process: 单进程内存预估(GB)
50
+ :param timeout_per_task: 单任务超时时间(秒)
51
+ :param max_retries: 最大重试次数
52
+ :param progress_callback: 进度回调函数 (当前完成数, 总数)
28
53
  """
29
- Initialize a PEx instance, internally creating a ParallelExecutor instance.
54
+ # 时间记录扩展
55
+ self.start_dt = datetime.datetime.now()
56
+ self.end_dt = None
57
+ self.progress_callback = progress_callback
58
+
59
+ super().__init__(max_workers=max_workers, chunk_size=chunk_size, mem_per_process=mem_per_process, timeout_per_task=timeout_per_task, max_retries=max_retries)
30
60
 
31
- Args:
32
- *args: Positional arguments passed to ParallelExecutor.
33
- **kwargs: Keyword arguments passed to ParallelExecutor.
61
+ logging.info(f"PEx initialized at {self.start_dt:%Y-%m-%d %H:%M:%S}")
62
+
63
+ def run(self, func: Callable, params: List[Tuple], chunk_size: Optional[int] = None) -> List[Any]:
34
64
  """
35
- self.executor = self.ParallelExecutor(*args, **kwargs)
65
+ 执行并行任务 (增强版)
36
66
 
37
- def __getattr__(self, attr: str) -> Any:
67
+ :param func: 目标函数,需能序列化(pickle)
68
+ :param params: 参数列表,每个元素为参数元组
69
+ :param chunk_size: 可选的分块大小
70
+ :return: 结果列表,与输入顺序一致
38
71
  """
39
- Delegate all undefined attribute access to the internal ParallelExecutor instance.
72
+ total_tasks = len(params)
73
+ if self.progress_callback:
74
+ self.progress_callback(0, total_tasks)
75
+
76
+ results = super().run(func, params, chunk_size)
77
+
78
+ if self.progress_callback:
79
+ self.progress_callback(total_tasks, total_tasks)
80
+
81
+ return results
82
+
83
+ def shutdown(self):
84
+ """增强关闭方法,记录结束时间"""
85
+ self.end_dt = datetime.datetime.now()
86
+ super().shutdown()
87
+ logging.info(f"PEx shutdown at {self.end_dt:%Y-%m-%d %H:%M:%S}")
88
+
89
+ def get_stats(self) -> Dict[str, Any]:
90
+ """获取统计信息 (扩展时间数据)"""
91
+ stats = super().get_stats()
92
+ stats.update({"start_time": self.start_dt.strftime("%Y-%m-%d %H:%M:%S"), "end_time": self.end_dt.strftime("%Y-%m-%d %H:%M:%S") if self.end_dt else "运行中", "total_seconds": round((self.end_dt - self.start_dt).total_seconds(), 3) if self.end_dt else None})
93
+ return stats
94
+
95
+ def format_stats(self) -> str:
96
+ """生成友好统计报告"""
97
+ stats = self.get_stats()
98
+ report = [
99
+ f"[{stats['start_time']}] 并行任务统计报告",
100
+ f"▪ 平台环境:{stats['platform'].upper()} ({stats['mode']}模式)",
101
+ f"▪ 资源使用:{stats['workers']}个工作进程 | 分块大小{stats['chunk_size']}",
102
+ f"▪ 任务统计:成功处理{stats['total_tasks']}个任务 (失败{stats['total_tasks'] - sum(1 for r in self.results if r is not None)})",
103
+ f"▪ 时间统计:总耗时{stats['total_seconds']}秒",
104
+ ]
105
+ if "avg_task_throughput" in stats:
106
+ report.append(f"▪ 吞吐性能:{stats['avg_task_throughput']:.1f} 任务/秒")
107
+ return "\n".join(report)
108
+
109
+ def __enter__(self):
110
+ """支持上下文管理器"""
111
+ return self
112
+
113
+ def __exit__(self, exc_type, exc_val, exc_tb):
114
+ """退出时自动关闭"""
115
+ self.shutdown()
40
116
 
41
- Args:
42
- attr (str): The name of the attribute to access.
43
117
 
44
- Returns:
45
- Any: The value of the corresponding attribute.
46
- """
47
- return getattr(self.executor, attr)
48
118
 
49
119
 
50
120
  def email(title: str = "Title", content: Optional[str] = None, send_to: str = "10001@qq.com") -> None:
@@ -91,7 +161,7 @@ def pbar(
91
161
 
92
162
  Returns:
93
163
  Any: An instance of ColorProgressBar.
94
-
164
+
95
165
  Example:
96
166
  >>> for i in pbar(range(10), description="Processing"):
97
167
  ... time.sleep(0.1)
@@ -117,3 +187,21 @@ def pbar(
117
187
  speed_estimate_period=speed_estimate_period,
118
188
  next_line=next_line,
119
189
  )
190
+
191
+
192
+ # 使用示例
193
+ if __name__ == "__main__":
194
+
195
+ def sample_task(x):
196
+ import time
197
+
198
+ time.sleep(0.1)
199
+ return x * 2
200
+
201
+ def progress_handler(current, total):
202
+ print(f"\r进度: {current}/{total} ({current / total:.1%})", end="")
203
+
204
+ with PEx(max_workers=4, progress_callback=progress_handler) as executor:
205
+ results = executor.run(sample_task, [(i,) for i in range(10)])
206
+
207
+ print("\n" + executor.format_stats())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oafuncs
3
- Version: 0.0.98.3
3
+ Version: 0.0.98.5
4
4
  Summary: Oceanic and Atmospheric Functions
5
5
  Home-page: https://github.com/Industry-Pays/OAFuncs
6
6
  Author: Kun Liu
@@ -25,6 +25,7 @@ Requires-Dist: rich
25
25
  Requires-Dist: pathlib
26
26
  Requires-Dist: requests
27
27
  Requires-Dist: bs4
28
+ Requires-Dist: httpx
28
29
  Requires-Dist: matplotlib
29
30
  Requires-Dist: netCDF4
30
31
  Requires-Dist: xlrd
@@ -7,7 +7,7 @@ oafuncs/oa_file.py,sha256=goF5iRXJFFCIKhIjlkCnYYt0EYlJb_4r8AeYNZ0-SOk,16209
7
7
  oafuncs/oa_help.py,sha256=_4AZgRDq5Or0vauNvq5IDDHIBoBfdOQtzak-mG1wwAw,4537
8
8
  oafuncs/oa_nc.py,sha256=L1gqXxg93kIDsMOa87M0o-53KVmdqCipnXeF9XfzfY8,10513
9
9
  oafuncs/oa_python.py,sha256=NkopwkYFGSEuVljnTBvXCl6o2CeyRNBqRXSsUl3euEE,5192
10
- oafuncs/oa_tool.py,sha256=8y0X3KXNLbYchr5hBHCwhdsA_1VDEnzsZVqcM5sNeog,4484
10
+ oafuncs/oa_tool.py,sha256=UNdiXKWfk860eb01vSGH8XN_Bd3CP7ihaspRrudday0,7983
11
11
  oafuncs/_data/hycom.png,sha256=MadKs6Gyj5n9-TOu7L4atQfTXtF9dvN9w-tdU9IfygI,10945710
12
12
  oafuncs/_data/oafuncs.png,sha256=o3VD7wm-kwDea5E98JqxXl04_78cBX7VcdUt7uQXGiU,3679898
13
13
  oafuncs/_script/cprogressbar.py,sha256=wRU3SFPFtMI7ER26tTzg223kVKNo5RDWE9CzdIgUsuE,15771
@@ -15,17 +15,16 @@ oafuncs/_script/email.py,sha256=lL4HGKrr524-g0xLlgs-4u7x4-u7DtgNoD9AL8XJKj4,3058
15
15
  oafuncs/_script/netcdf_merge.py,sha256=_EPF9Xj4HOVC9sZpi1lt62-Aq6pMlgsgwaajEBLhW6g,5092
16
16
  oafuncs/_script/netcdf_modify.py,sha256=sGRUYNhfGgf9JV70rnBzw3bzuTRSXzBTL_RMDnDPeLQ,4552
17
17
  oafuncs/_script/netcdf_write.py,sha256=iO1Qv9bp6RLiw1D8Nrv7tX_8X-diUZaX3Nxhk6pJ5Nw,8556
18
- oafuncs/_script/parallel.py,sha256=FS9FgaByq2yb9j6nL-Y0xP1VLvp4USMLBFMRsJDoqeQ,21848
19
- oafuncs/_script/parallel_example_usage.py,sha256=uLvE7iwkMn9Cyq6-wk5_RpbQk7PXM9d16-26lTknW9s,2646
18
+ oafuncs/_script/parallel.py,sha256=dRT7w_rBnR3mZkUlO6v6j05SwBTQpTccOna5CXI5Msg,8196
19
+ oafuncs/_script/parallel_test.py,sha256=0GBqZOX7IaCOKF2t1y8N8YYu53GJ33OkfsWgpvZNqM4,372
20
20
  oafuncs/_script/plot_dataset.py,sha256=zkSEnO_-biyagorwWXPoihts_cwuvripzEt-l9bHJ2E,13989
21
21
  oafuncs/_script/replace_file_content.py,sha256=eCFZjnZcwyRvy6b4mmIfBna-kylSZTyJRfgXd6DdCjk,5982
22
- oafuncs/oa_down/User_Agent-list.txt,sha256=pazxSip8_lphEBOPHG902zmIBUg8sBKXgmqp_g6j_E4,661062
22
+ oafuncs/oa_down/User_Agent-list.txt,sha256=pHaMlElMvZ8TG4vf4BqkZYKqe0JIGkr4kCN0lM1Y9FQ,514295
23
23
  oafuncs/oa_down/__init__.py,sha256=kRX5eTUCbAiz3zTaQM1501paOYS_3fizDN4Pa0mtNUA,585
24
- oafuncs/oa_down/hycom_3hourly.py,sha256=Xi6LuD3DIiYq2gYYBVxY3OpVvfy3RkSMzNkOX2isSK8,52915
25
- oafuncs/oa_down/hycom_3hourly_20250407.py,sha256=DQd_NmQgmSqu7jsrfpDB7k23mkUEy9kyWs-dLUg7GDw,64472
24
+ oafuncs/oa_down/hycom_3hourly.py,sha256=ERH24OOT62IiOSk5IiSnqad_c13zL7-uD5lAMdbJDiQ,53576
26
25
  oafuncs/oa_down/idm.py,sha256=4z5IvgfTyIKEI1kOtqXZwN7Jnfjwp6qDBOIoVyOLp0I,1823
27
26
  oafuncs/oa_down/literature.py,sha256=2bF9gSKQbzcci9LcKE81j8JEjIJwON7jbwQB3gDDA3E,11331
28
- oafuncs/oa_down/test_ua.py,sha256=0IQq3NjqfNr7KkyjS_U-a4mYu-r-E7gzawwo4IfEa6Y,10851
27
+ oafuncs/oa_down/test_ua.py,sha256=l8MCD6yU2W75zRPTDKUZTJhCWNF9lfk-MiSFqAqKH1M,1398
29
28
  oafuncs/oa_down/user_agent.py,sha256=TsPcAxFmMTYAEHRFjurI1bQBJfDhcA70MdHoUPwQmks,785
30
29
  oafuncs/oa_model/__init__.py,sha256=__ImltHkP1bSsIpsmKpDE8QwwA-2Z8K7mZUHGGcRdro,484
31
30
  oafuncs/oa_model/roms/__init__.py,sha256=g-_iv2vUFUnSsKWc7pzGRfkNUvhxfG-Bn4deqfGwxyo,474
@@ -36,8 +35,8 @@ oafuncs/oa_sign/__init__.py,sha256=QKqTFrJDFK40C5uvk48GlRRbGFzO40rgkYwu6dYxatM,5
36
35
  oafuncs/oa_sign/meteorological.py,sha256=8091SHo2L8kl4dCFmmSH5NGVHDku5i5lSiLEG5DLnOQ,6489
37
36
  oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
38
37
  oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
39
- oafuncs-0.0.98.3.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
40
- oafuncs-0.0.98.3.dist-info/METADATA,sha256=1-5l6aAaOFaZ9U0pSE6f1944hrE01bLGCBLPonbEXeU,4220
41
- oafuncs-0.0.98.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
42
- oafuncs-0.0.98.3.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
43
- oafuncs-0.0.98.3.dist-info/RECORD,,
38
+ oafuncs-0.0.98.5.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
39
+ oafuncs-0.0.98.5.dist-info/METADATA,sha256=YwSyTAse2NhMIfM_22BNOJCDLh8Mgy3X_G5zvtCKyPc,4242
40
+ oafuncs-0.0.98.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
41
+ oafuncs-0.0.98.5.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
42
+ oafuncs-0.0.98.5.dist-info/RECORD,,
@@ -1,83 +0,0 @@
1
- #!/usr/bin/env python
2
- # coding=utf-8
3
- """
4
- Author: Liu Kun && 16031215@qq.com
5
- Date: 2025-03-18 19:14:19
6
- LastEditors: Liu Kun && 16031215@qq.com
7
- LastEditTime: 2025-03-18 19:18:38
8
- FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\_script\\parallel_example_usage.py
9
- Description:
10
- EditPlatform: vscode
11
- ComputerInfo: XPS 15 9510
12
- SystemInfo: Windows 11
13
- Python Version: 3.12
14
- """
15
-
16
- import logging
17
- import time
18
- from auto_optimized_parallel_executor import ParallelExecutor
19
-
20
- # 设置日志
21
- logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
22
-
23
-
24
- # 示例函数
25
- def compute_intensive_task(n):
26
- """计算密集型任务示例"""
27
- result = 0
28
- for i in range(n):
29
- result += i**0.5
30
- return result
31
-
32
-
33
- def io_intensive_task(seconds, value):
34
- """IO密集型任务示例"""
35
- time.sleep(seconds) # 模拟IO操作
36
- return f"Processed {value}"
37
-
38
-
39
- def main():
40
- # 创建自动优化的执行器
41
- executor = ParallelExecutor()
42
-
43
- # 打印选择的模式和工作线程/进程数量
44
- print(f"自动选择的执行模式: {executor.mode}")
45
- print(f"自动选择的工作线程/进程数: {executor.max_workers}")
46
- print(f"运行平台: {executor.platform}")
47
-
48
- # 示例1: 计算密集型任务
49
- print("\n运行计算密集型任务...")
50
- params = [(1000000,) for _ in range(20)]
51
- results = executor.run(compute_intensive_task, params)
52
- print(f"完成计算密集型任务,结果数量: {len(results)}")
53
-
54
- # 示例2: IO密集型任务
55
- print("\n运行IO密集型任务...")
56
- io_params = [(0.1, f"item-{i}") for i in range(30)]
57
- io_results = executor.run(io_intensive_task, io_params)
58
- print(f"完成IO密集型任务,结果示例: {io_results[:3]}")
59
-
60
- # 示例3: 使用map接口
61
- print("\n使用map接口...")
62
- numbers = list(range(1, 11))
63
- squared = list(executor.map(lambda x: x * x, numbers))
64
- print(f"Map结果: {squared}")
65
-
66
- # 示例4: 使用imap_unordered接口(乱序返回结果)
67
- print("\n使用imap_unordered接口...")
68
- for i, result in enumerate(executor.imap_unordered(lambda x: x * x * x, range(1, 11))):
69
- print(f"收到结果 #{i}: {result}")
70
-
71
- # 示例5: 使用gather执行不同函数
72
- print("\n使用gather接口执行不同函数...")
73
- tasks = [(compute_intensive_task, (500000,)), (io_intensive_task, (0.2, "task1")), (io_intensive_task, (0.1, "task2")), (compute_intensive_task, (300000,))]
74
- gather_results = executor.gather(tasks)
75
- print(f"Gather结果: {gather_results}")
76
-
77
- # 关闭执行器
78
- executor.shutdown()
79
- print("\n执行器已关闭")
80
-
81
-
82
- if __name__ == "__main__":
83
- main()