ezKit 1.10.0__py3-none-any.whl → 1.10.2__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.
- ezKit/utils.py +57 -70
- {ezKit-1.10.0.dist-info → ezKit-1.10.2.dist-info}/METADATA +1 -1
- {ezKit-1.10.0.dist-info → ezKit-1.10.2.dist-info}/RECORD +6 -6
- {ezKit-1.10.0.dist-info → ezKit-1.10.2.dist-info}/LICENSE +0 -0
- {ezKit-1.10.0.dist-info → ezKit-1.10.2.dist-info}/WHEEL +0 -0
- {ezKit-1.10.0.dist-info → ezKit-1.10.2.dist-info}/top_level.txt +0 -0
ezKit/utils.py
CHANGED
@@ -9,12 +9,11 @@ import time
|
|
9
9
|
import tomllib
|
10
10
|
from copy import deepcopy
|
11
11
|
from itertools import islice
|
12
|
-
from multiprocessing import Pool
|
12
|
+
from multiprocessing import Pool
|
13
13
|
from multiprocessing.pool import ThreadPool
|
14
14
|
from pathlib import Path
|
15
15
|
from shutil import rmtree
|
16
|
-
from
|
17
|
-
from typing import Any, Callable, List, Optional, Union
|
16
|
+
from typing import Any, Callable, List, Union
|
18
17
|
from urllib.parse import ParseResult, urlparse
|
19
18
|
from uuid import uuid4
|
20
19
|
|
@@ -742,31 +741,23 @@ def parent_dir(
|
|
742
741
|
# --------------------------------------------------------------------------------------------------
|
743
742
|
|
744
743
|
|
745
|
-
def retry(
|
746
|
-
times: int,
|
747
|
-
func: Callable,
|
748
|
-
**kwargs
|
749
|
-
):
|
744
|
+
def retry(func: Callable, times: int = 3, **kwargs):
|
750
745
|
"""重试"""
|
746
|
+
|
751
747
|
# 函数传递参数: https://stackoverflow.com/a/803632
|
752
748
|
# callable() 判断类型是非为函数: https://stackoverflow.com/a/624939
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
#
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
# 执行函数
|
762
|
-
try:
|
763
|
-
return func(**kwargs)
|
764
|
-
except Exception as e:
|
765
|
-
logger.exception(e)
|
749
|
+
|
750
|
+
for attempt in range(times):
|
751
|
+
try:
|
752
|
+
# 执行函数并结果
|
753
|
+
return func(**kwargs)
|
754
|
+
except Exception as e:
|
755
|
+
logger.exception(e)
|
756
|
+
if attempt < (times - 1):
|
766
757
|
logger.info('retrying ...')
|
767
|
-
|
768
|
-
|
769
|
-
|
758
|
+
else:
|
759
|
+
logger.error("all retries failed")
|
760
|
+
return False
|
770
761
|
|
771
762
|
|
772
763
|
# --------------------------------------------------------------------------------------------------
|
@@ -1199,65 +1190,61 @@ def delete_directory(
|
|
1199
1190
|
# --------------------------------------------------------------------------------------------------
|
1200
1191
|
|
1201
1192
|
|
1202
|
-
def
|
1193
|
+
def processor(
|
1203
1194
|
process_func: Callable,
|
1204
|
-
process_data: Any
|
1195
|
+
process_data: List[Any],
|
1205
1196
|
process_num: int = 2,
|
1206
1197
|
thread: bool = False,
|
1207
1198
|
**kwargs
|
1208
|
-
) ->
|
1209
|
-
"""
|
1210
|
-
|
1211
|
-
|
1212
|
-
#
|
1199
|
+
) -> Union[List[Any], bool]:
|
1200
|
+
"""使用多线程或多进程对数据进行并行处理"""
|
1201
|
+
|
1202
|
+
# :param process_func: 处理函数
|
1203
|
+
# :param process_data: 待处理数据列表
|
1204
|
+
# :param process_num: 并行数量
|
1205
|
+
# :param thread: 是否使用多线程
|
1206
|
+
# :param kwargs: 其他可选参数传递给线程池或进程池
|
1207
|
+
# :return: 处理后的结果列表或 False(异常情况)
|
1208
|
+
#
|
1209
|
+
# MultiThread 多线程
|
1210
|
+
# MultiProcess 多进程
|
1211
|
+
#
|
1212
|
+
# ThreadPool 线程池
|
1213
|
+
# Pool 进程池
|
1214
|
+
#
|
1213
1215
|
# ThreadPool 共享内存, Pool 不共享内存
|
1214
1216
|
# ThreadPool 可以解决 Pool 在某些情况下产生的 Can't pickle local object 的错误
|
1215
|
-
#
|
1216
|
-
|
1217
|
+
# https://stackoverflow.com/a/58897266
|
1218
|
+
#
|
1219
|
+
# 如果要启动一个新的进程或者线程, 将 process_num 设置为 1 即可
|
1217
1220
|
|
1218
|
-
|
1219
|
-
if len(process_data) <= process_num:
|
1220
|
-
process_num = len(process_data)
|
1221
|
-
_data = process_data
|
1222
|
-
else:
|
1223
|
-
_data = list_split(process_data, process_num, equally=True)
|
1221
|
+
try:
|
1224
1222
|
|
1225
|
-
|
1223
|
+
# 检查参数
|
1224
|
+
if not check_arguments([(process_data, list, "process_data")]):
|
1226
1225
|
return False
|
1227
1226
|
|
1228
|
-
#
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
# 多进程
|
1236
|
-
logger.info("execute multi process ......")
|
1237
|
-
with Pool(process_num, **kwargs) as p:
|
1238
|
-
return p.map(process_func, _data)
|
1227
|
+
# 确保并行数不超过数据量
|
1228
|
+
process_num = min(len(process_data), process_num)
|
1229
|
+
_data_chunks = (
|
1230
|
+
list_split(process_data, process_num, equally=True)
|
1231
|
+
if process_num > 1
|
1232
|
+
else process_data
|
1233
|
+
)
|
1239
1234
|
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1235
|
+
if not _data_chunks:
|
1236
|
+
logger.error("data chunks error")
|
1237
|
+
return False
|
1243
1238
|
|
1239
|
+
logger.info(
|
1240
|
+
f"Starting {'multi-threading' if thread else 'multi-processing'} with {process_num} workers..."
|
1241
|
+
)
|
1242
|
+
|
1243
|
+
# 执行多线程或多进程任务
|
1244
|
+
pool_cls = ThreadPool if thread else Pool
|
1245
|
+
with pool_cls(process_num, **kwargs) as pool:
|
1246
|
+
return pool.map(process_func, _data_chunks)
|
1244
1247
|
|
1245
|
-
def new_process(
|
1246
|
-
process_func: Callable,
|
1247
|
-
process_data: Any = None,
|
1248
|
-
thread: bool = False,
|
1249
|
-
daemon: bool = True,
|
1250
|
-
**kwargs
|
1251
|
-
) -> Thread | Process | bool:
|
1252
|
-
"""New Process"""
|
1253
|
-
try:
|
1254
|
-
if isTrue(thread, bool):
|
1255
|
-
process = Thread(target=process_func, args=process_data, **kwargs)
|
1256
|
-
else:
|
1257
|
-
process = Process(target=process_func, args=process_data, **kwargs)
|
1258
|
-
process.daemon = daemon
|
1259
|
-
process.start()
|
1260
|
-
return process
|
1261
1248
|
except Exception as e:
|
1262
1249
|
logger.exception(e)
|
1263
1250
|
return False
|
@@ -9,10 +9,10 @@ ezKit/qywx.py,sha256=X_H4fzP-iEqeDEbumr7D1bXi6dxczaxfO8iyutzy02s,7171
|
|
9
9
|
ezKit/redis.py,sha256=g2_V4jvq0djRc20jLZkgeAeF_bYrq-Rbl_kHcCUPZcA,1965
|
10
10
|
ezKit/sendemail.py,sha256=tRXCsJm_RfTJ9xEWe_lTQ5kOs2JxHGPXvq0oWA7prq0,7263
|
11
11
|
ezKit/token.py,sha256=HKREyZj_T2S8-aFoFIrBXTaCKExQq4zE66OHXhGHqQg,1750
|
12
|
-
ezKit/utils.py,sha256=
|
12
|
+
ezKit/utils.py,sha256=xfubEO3tMaPp9idKst-xwdSuSTtRQfsO-k9FlipnHT4,42515
|
13
13
|
ezKit/xftp.py,sha256=XyIdr_2rxRVLqPofG6fIYWhAMVsFwTyp46dg5P9FLW4,7774
|
14
|
-
ezKit-1.10.
|
15
|
-
ezKit-1.10.
|
16
|
-
ezKit-1.10.
|
17
|
-
ezKit-1.10.
|
18
|
-
ezKit-1.10.
|
14
|
+
ezKit-1.10.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
15
|
+
ezKit-1.10.2.dist-info/METADATA,sha256=BHUZCWlCgc_I0J4s2LbKakrUWMJALLqvIGAm2g0QEww,191
|
16
|
+
ezKit-1.10.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
17
|
+
ezKit-1.10.2.dist-info/top_level.txt,sha256=aYLB_1WODsqNTsTFWcKP-BN0KCTKcV-HZJ4zlHkCFw8,6
|
18
|
+
ezKit-1.10.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|