oafuncs 0.0.98.3__py3-none-any.whl → 0.0.98.4__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/_script/parallel.py +158 -509
- oafuncs/_script/parallel_test.py +14 -0
- oafuncs/oa_down/User_Agent-list.txt +1 -1611
- oafuncs/oa_down/hycom_3hourly.py +109 -75
- oafuncs/oa_down/hycom_3hourly_20250416.py +1191 -0
- oafuncs/oa_down/test_ua.py +27 -138
- oafuncs/oa_tool.py +118 -30
- {oafuncs-0.0.98.3.dist-info → oafuncs-0.0.98.4.dist-info}/METADATA +2 -1
- {oafuncs-0.0.98.3.dist-info → oafuncs-0.0.98.4.dist-info}/RECORD +12 -11
- oafuncs/_script/parallel_example_usage.py +0 -83
- {oafuncs-0.0.98.3.dist-info → oafuncs-0.0.98.4.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.98.3.dist-info → oafuncs-0.0.98.4.dist-info}/licenses/LICENSE.txt +0 -0
- {oafuncs-0.0.98.3.dist-info → oafuncs-0.0.98.4.dist-info}/top_level.txt +0 -0
oafuncs/oa_down/test_ua.py
CHANGED
@@ -1,151 +1,40 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
# coding=utf-8
|
3
|
-
"""
|
4
|
-
Author: Liu Kun && 16031215@qq.com
|
5
|
-
Date: 2024-12-01 19:32:25
|
6
|
-
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
-
LastEditTime: 2024-12-10 11:16:36
|
8
|
-
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_down\\test.py
|
9
|
-
Description:
|
10
|
-
EditPlatform: vscode
|
11
|
-
ComputerInfo: XPS 15 9510
|
12
|
-
SystemInfo: Windows 11
|
13
|
-
Python Version: 3.12
|
14
|
-
"""
|
15
|
-
|
16
|
-
import os
|
17
|
-
import random
|
18
1
|
import re
|
19
2
|
|
20
3
|
|
21
|
-
def
|
22
|
-
#
|
23
|
-
# 这个正则表达式检查User Agent是否包含常见的浏览器信息格式
|
4
|
+
def is_valid_ua(ua):
|
5
|
+
# 更宽松的 UA 验证规则
|
24
6
|
pattern = re.compile(
|
25
|
-
r"
|
26
|
-
|
27
|
-
|
28
|
-
|
7
|
+
r"""
|
8
|
+
^Mozilla/(4\.0|5\.0) # 必须以 Mozilla/4.0 或 5.0 开头
|
9
|
+
\s+ # 空格
|
10
|
+
\(.*?\) # 操作系统信息
|
11
|
+
\s+ # 空格
|
12
|
+
(AppleWebKit/|Gecko/|Trident/|Version/|Edge/)? # 浏览器引擎或版本标识(可选)
|
13
|
+
\d+(\.\d+)* # 至少一个版本号(小数部分可选)
|
14
|
+
.* # 允许后续扩展信息
|
15
|
+
$ # 行尾
|
16
|
+
""",
|
17
|
+
re.VERBOSE,
|
29
18
|
)
|
19
|
+
return re.match(pattern, ua.strip()) is not None
|
30
20
|
|
31
|
-
# 使用正则表达式匹配User Agent字符串
|
32
|
-
if pattern.match(user_agent):
|
33
|
-
return True
|
34
|
-
else:
|
35
|
-
return False
|
36
|
-
|
37
|
-
|
38
|
-
def get_ua():
|
39
|
-
current_dir = os.path.dirname(os.path.abspath(__file__))
|
40
|
-
ua_file_txt = os.path.join(current_dir, "User_Agent-list.txt")
|
41
|
-
|
42
|
-
with open(ua_file_txt, "r") as f:
|
43
|
-
ua_list = f.readlines()
|
44
|
-
# 去掉换行符和空行
|
45
|
-
ua_list = [line.strip() for line in ua_list if line.strip()]
|
46
21
|
|
47
|
-
|
22
|
+
def main():
|
23
|
+
input_file = r"E:\Code\Python\My_Funcs\OAFuncs\oafuncs\oa_down\User_Agent-list-old.txt"
|
24
|
+
output_file = r"E:\Code\Python\My_Funcs\OAFuncs\oafuncs\oa_down\User_Agent-list.txt"
|
48
25
|
|
26
|
+
valid_uas = []
|
27
|
+
with open(input_file, "r", encoding="utf-8") as f:
|
28
|
+
for line in f:
|
29
|
+
line = line.strip()
|
30
|
+
if line and is_valid_ua(line):
|
31
|
+
valid_uas.append(line)
|
49
32
|
|
50
|
-
|
51
|
-
|
52
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 OPR/26.0.1656.60",
|
53
|
-
"Opera/8.0 (Windows NT 5.1; U; en)",
|
54
|
-
"Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50",
|
55
|
-
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.50",
|
56
|
-
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
|
57
|
-
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
|
58
|
-
"Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
|
59
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0",
|
60
|
-
"Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10",
|
61
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1",
|
62
|
-
"Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1",
|
63
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
|
64
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36",
|
65
|
-
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
|
66
|
-
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
67
|
-
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
68
|
-
"Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
69
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
|
70
|
-
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
|
71
|
-
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16",
|
72
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
|
73
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36",
|
74
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
|
75
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
|
76
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
|
77
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
|
78
|
-
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
|
79
|
-
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
|
80
|
-
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
|
81
|
-
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
|
82
|
-
"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0",
|
83
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; SE 2.X MetaSr 1.0)",
|
84
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
|
85
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.4.3.4000 Chrome/30.0.1599.101 Safari/537.36",
|
86
|
-
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
|
87
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36",
|
88
|
-
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4094.1 Safari/537.36",
|
89
|
-
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
90
|
-
"Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
91
|
-
"Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
|
92
|
-
"Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
|
93
|
-
"Mozilla/5.0 (Linux; U; Android 2.2.1; zh-cn; HTC_Wildfire_A3333 Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
94
|
-
"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
95
|
-
"MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
96
|
-
"Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
|
97
|
-
"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
|
98
|
-
"Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
|
99
|
-
"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
|
100
|
-
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;",
|
101
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
|
102
|
-
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
|
103
|
-
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
|
104
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
|
105
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
|
106
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
|
107
|
-
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
|
108
|
-
"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
109
|
-
"Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124",
|
110
|
-
"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
|
111
|
-
"UCWEB7.0.2.37/28/999",
|
112
|
-
"NOKIA5700/UCWEB7.0.2.37/28/999",
|
113
|
-
"Openwave/UCWEB7.0.2.37/28/999",
|
114
|
-
"Openwave/UCWEB7.0.2.37/28/999",
|
115
|
-
]
|
116
|
-
with open(newtxtfile, "w") as f:
|
117
|
-
for line in ua_list:
|
118
|
-
f.write(line + "\n")
|
119
|
-
# print(f'Using User-Agent: {ua}')
|
120
|
-
ua = random.choice(ua_list)
|
121
|
-
return ua
|
33
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
34
|
+
f.write("\n".join(valid_uas))
|
122
35
|
|
36
|
+
print(f"[Linux 兼容模式] 有效UA已保存到 {output_file},共 {len(valid_uas)} 条")
|
123
37
|
|
124
|
-
# get_ua_org()
|
125
38
|
|
126
39
|
if __name__ == "__main__":
|
127
|
-
|
128
|
-
|
129
|
-
with open(txtfile, "r") as f:
|
130
|
-
lines = f.readlines()
|
131
|
-
# 去掉换行符和空行
|
132
|
-
lines = [line.strip() for line in lines if line.strip()]
|
133
|
-
""" new_line = []
|
134
|
-
for i in range(len(lines)):
|
135
|
-
if '/' in lines[i]:
|
136
|
-
new_line.append(lines[i])
|
137
|
-
else:
|
138
|
-
print(lines[i]) """
|
139
|
-
|
140
|
-
new_line = []
|
141
|
-
for line in lines:
|
142
|
-
if is_valid_user_agent(line):
|
143
|
-
# print(line)
|
144
|
-
new_line.append(line)
|
145
|
-
else:
|
146
|
-
print(f"Invalid User-Agent: {line}")
|
147
|
-
|
148
|
-
newtxtfile = r"E:\Code\Python\My_Funcs\OAFuncs\oafuncs\oa_down\ua_list_new.txt"
|
149
|
-
with open(newtxtfile, "w") as f:
|
150
|
-
for line in new_line:
|
151
|
-
f.write(line + "\n")
|
40
|
+
main()
|
oafuncs/oa_tool.py
CHANGED
@@ -1,50 +1,120 @@
|
|
1
|
-
|
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
|
-
|
11
|
-
allowing direct calls to PEx methods to achieve the same effect as ParallelExecutor.
|
14
|
+
并行执行器扩展类 (ParallelExecutor Extend)
|
12
15
|
|
13
|
-
|
14
|
-
# Create a PEx instance
|
15
|
-
executor = PEx(max_workers=4)
|
16
|
+
继承自 ParallelExecutor,提供更简洁的接口和增强功能:
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
特点:
|
19
|
+
- 自动时间统计 (开始/结束时间、总耗时)
|
20
|
+
- 增强的错误处理机制
|
21
|
+
- 友好的统计输出格式
|
22
|
+
- 支持进度回调函数
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
65
|
+
执行并行任务 (增强版)
|
36
66
|
|
37
|
-
|
67
|
+
:param func: 目标函数,需能序列化(pickle)
|
68
|
+
:param params: 参数列表,每个元素为参数元组
|
69
|
+
:param chunk_size: 可选的分块大小
|
70
|
+
:return: 结果列表,与输入顺序一致
|
38
71
|
"""
|
39
|
-
|
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
|
+
Version: 0.0.98.4
|
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=
|
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,18 @@ 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=
|
19
|
-
oafuncs/_script/
|
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=
|
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=
|
24
|
+
oafuncs/oa_down/hycom_3hourly.py,sha256=heG4L_eyPsc8pgUASCXYYJEdPGAY7rtRWQsiy-qrSxE,54202
|
25
25
|
oafuncs/oa_down/hycom_3hourly_20250407.py,sha256=DQd_NmQgmSqu7jsrfpDB7k23mkUEy9kyWs-dLUg7GDw,64472
|
26
|
+
oafuncs/oa_down/hycom_3hourly_20250416.py,sha256=X_fcV_xeJtYD-PB3GRdFWNHMPOVUYgh17MgWOtrdIbc,53493
|
26
27
|
oafuncs/oa_down/idm.py,sha256=4z5IvgfTyIKEI1kOtqXZwN7Jnfjwp6qDBOIoVyOLp0I,1823
|
27
28
|
oafuncs/oa_down/literature.py,sha256=2bF9gSKQbzcci9LcKE81j8JEjIJwON7jbwQB3gDDA3E,11331
|
28
|
-
oafuncs/oa_down/test_ua.py,sha256=
|
29
|
+
oafuncs/oa_down/test_ua.py,sha256=l8MCD6yU2W75zRPTDKUZTJhCWNF9lfk-MiSFqAqKH1M,1398
|
29
30
|
oafuncs/oa_down/user_agent.py,sha256=TsPcAxFmMTYAEHRFjurI1bQBJfDhcA70MdHoUPwQmks,785
|
30
31
|
oafuncs/oa_model/__init__.py,sha256=__ImltHkP1bSsIpsmKpDE8QwwA-2Z8K7mZUHGGcRdro,484
|
31
32
|
oafuncs/oa_model/roms/__init__.py,sha256=g-_iv2vUFUnSsKWc7pzGRfkNUvhxfG-Bn4deqfGwxyo,474
|
@@ -36,8 +37,8 @@ oafuncs/oa_sign/__init__.py,sha256=QKqTFrJDFK40C5uvk48GlRRbGFzO40rgkYwu6dYxatM,5
|
|
36
37
|
oafuncs/oa_sign/meteorological.py,sha256=8091SHo2L8kl4dCFmmSH5NGVHDku5i5lSiLEG5DLnOQ,6489
|
37
38
|
oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
|
38
39
|
oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
|
39
|
-
oafuncs-0.0.98.
|
40
|
-
oafuncs-0.0.98.
|
41
|
-
oafuncs-0.0.98.
|
42
|
-
oafuncs-0.0.98.
|
43
|
-
oafuncs-0.0.98.
|
40
|
+
oafuncs-0.0.98.4.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
|
41
|
+
oafuncs-0.0.98.4.dist-info/METADATA,sha256=VWSW69LEhmMu9FHH_e0WcNT-YXme3mdxlNvMedU48tY,4242
|
42
|
+
oafuncs-0.0.98.4.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
43
|
+
oafuncs-0.0.98.4.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
|
44
|
+
oafuncs-0.0.98.4.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()
|
File without changes
|
File without changes
|
File without changes
|