kevin-toolbox-dev 1.3.2__py3-none-any.whl → 1.3.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.
- kevin_toolbox/__init__.py +2 -2
- kevin_toolbox/data_flow/core/reader/file_iterative_reader.py +44 -9
- kevin_toolbox/data_flow/core/reader/unified_reader.py +2 -2
- kevin_toolbox/data_flow/file/json_/converter/__init__.py +2 -2
- kevin_toolbox/data_flow/file/json_/converter/escape_tuple_and_set.py +23 -0
- kevin_toolbox/data_flow/file/json_/converter/{unescape_tuple.py → unescape_tuple_and_set.py} +7 -5
- kevin_toolbox/data_flow/file/json_/read_json.py +3 -3
- kevin_toolbox/data_flow/file/json_/write_json.py +3 -3
- kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_reader.py +6 -5
- kevin_toolbox/data_flow/file/kevin_notation/read.py +4 -2
- kevin_toolbox/data_flow/file/kevin_notation/test/test_kevin_notation.py +15 -3
- kevin_toolbox/data_flow/file/markdown/generate_table.py +2 -2
- kevin_toolbox/math/utils/__init__.py +1 -1
- kevin_toolbox/math/utils/{spilt_integer_most_evenly.py → split_integer_most_evenly.py} +2 -2
- kevin_toolbox/nested_dict_list/serializer/__init__.py +1 -0
- kevin_toolbox/nested_dict_list/serializer/read.py +11 -4
- kevin_toolbox/nested_dict_list/serializer/saved_node_name_builder.py +31 -0
- kevin_toolbox/nested_dict_list/serializer/write.py +51 -26
- kevin_toolbox/nested_dict_list/value_parser/__init__.py +1 -0
- kevin_toolbox/nested_dict_list/value_parser/replace_identical_with_reference.py +127 -0
- kevin_toolbox/patches/for_numpy/random/get_rng.py +47 -1
- kevin_toolbox_dev-1.3.4.dist-info/METADATA +67 -0
- {kevin_toolbox_dev-1.3.2.dist-info → kevin_toolbox_dev-1.3.4.dist-info}/RECORD +25 -23
- kevin_toolbox/data_flow/file/json_/converter/escape_tuple.py +0 -20
- kevin_toolbox_dev-1.3.2.dist-info/METADATA +0 -96
- {kevin_toolbox_dev-1.3.2.dist-info → kevin_toolbox_dev-1.3.4.dist-info}/WHEEL +0 -0
- {kevin_toolbox_dev-1.3.2.dist-info → kevin_toolbox_dev-1.3.4.dist-info}/top_level.txt +0 -0
kevin_toolbox/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = "1.3.
|
1
|
+
__version__ = "1.3.4"
|
2
2
|
|
3
3
|
|
4
4
|
import os
|
@@ -12,5 +12,5 @@ os.system(
|
|
12
12
|
os.system(
|
13
13
|
f'python {os.path.split(__file__)[0]}/env_info/check_validity_and_uninstall.py '
|
14
14
|
f'--package_name kevin-toolbox-dev '
|
15
|
-
f'--expiration_timestamp
|
15
|
+
f'--expiration_timestamp 1727961379 --verbose 0'
|
16
16
|
)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import os
|
2
|
+
import copy
|
2
3
|
|
3
4
|
|
4
5
|
class File_Iterative_Reader:
|
@@ -12,11 +13,14 @@ class File_Iterative_Reader:
|
|
12
13
|
设定关键参数
|
13
14
|
必要参数:
|
14
15
|
file_path: 文件路径
|
16
|
+
file_obj: 文件对象
|
17
|
+
注意!!以上两个参数指定其一即可,同时指定时候,以后者为准。
|
15
18
|
读取模式相关参数:
|
16
19
|
paras_for_open: open() 函数的补充参数
|
17
20
|
mode: 读取模式,默认为 "lines"
|
18
21
|
"lines": 按行数计算批次大小
|
19
22
|
"bytes": 按字节数计算
|
23
|
+
注意!!以上两个参数在指定了 file_obj 参数后将失效。
|
20
24
|
chunk_size: 批次大小
|
21
25
|
默认为 1k
|
22
26
|
当为-1时,读取整个文件
|
@@ -51,6 +55,7 @@ class File_Iterative_Reader:
|
|
51
55
|
paras = {
|
52
56
|
# 必要参数
|
53
57
|
"file_path": None,
|
58
|
+
"file_obj": None,
|
54
59
|
# 读取模式相关参数
|
55
60
|
"paras_for_open": dict(mode="r", encoding='utf-8'),
|
56
61
|
"mode": "lines",
|
@@ -74,16 +79,21 @@ class File_Iterative_Reader:
|
|
74
79
|
assert mode in ["lines", "bytes"]
|
75
80
|
paras["chunk_size"] = int(paras["chunk_size"])
|
76
81
|
paras["loop_num"] = int(paras["loop_num"]) - 1
|
77
|
-
#
|
78
|
-
file_path = paras["file_path"]
|
79
|
-
assert isinstance(file_path, (str,)) and os.path.exists(file_path), \
|
80
|
-
Exception(f"Error: file {file_path} not exists!")
|
81
|
-
#
|
82
|
-
paras_for_open = paras["paras_for_open"]
|
83
|
-
assert isinstance(paras_for_open, (dict,))
|
84
82
|
|
85
83
|
# 获取文件对象
|
86
|
-
|
84
|
+
if paras["file_obj"] is None:
|
85
|
+
assert isinstance(paras["file_path"], (str,)) and os.path.isfile(paras["file_path"]), \
|
86
|
+
Exception(f'Error: file {paras["file_path"]} not exists!')
|
87
|
+
#
|
88
|
+
assert isinstance(paras["paras_for_open"], (dict,))
|
89
|
+
self.file = open(paras["file_path"], **paras["paras_for_open"])
|
90
|
+
else:
|
91
|
+
# 拷贝对象,防止修改外部对象
|
92
|
+
try:
|
93
|
+
self.file = copy.deepcopy(paras["file_obj"])
|
94
|
+
except:
|
95
|
+
self.file = open(paras["file_obj"].name, mode=paras["file_obj"].mode)
|
96
|
+
|
87
97
|
# 选择相应模式
|
88
98
|
self.__read_func = {"lines": self.__read_lines, "bytes": self.__read_bytes}[mode]
|
89
99
|
self.__jump_func = {"lines": self.__jump_lines, "bytes": self.__jump_bytes}[mode]
|
@@ -225,9 +235,34 @@ class File_Iterative_Reader:
|
|
225
235
|
if __name__ == "__main__":
|
226
236
|
import numpy as np
|
227
237
|
|
228
|
-
|
238
|
+
print("使用 file_path")
|
239
|
+
reader = File_Iterative_Reader(file_path="test/test_data/test_data.txt", chunk_size=2, drop=True, loop_num=2,
|
229
240
|
pre_jump_size=3, convert_func=lambda x: np.array(x))
|
230
241
|
for i in reader:
|
231
242
|
print(i)
|
232
243
|
|
233
244
|
del reader
|
245
|
+
|
246
|
+
print("使用 file_obj")
|
247
|
+
reader = File_Iterative_Reader(
|
248
|
+
file_obj=open("test/test_data/test_data.txt", "r"), chunk_size=2, drop=True, loop_num=2,
|
249
|
+
pre_jump_size=3, convert_func=lambda x: np.array(x))
|
250
|
+
for i in reader:
|
251
|
+
print(i)
|
252
|
+
|
253
|
+
del reader
|
254
|
+
|
255
|
+
print("从字符串构建文件对象作为 file_obj")
|
256
|
+
from io import StringIO
|
257
|
+
|
258
|
+
file_obj = StringIO(initial_value=open("test/test_data/test_data.txt", "r").read())
|
259
|
+
reader = File_Iterative_Reader(
|
260
|
+
file_obj=file_obj, chunk_size=2, drop=True, loop_num=2,
|
261
|
+
pre_jump_size=3, convert_func=lambda x: np.array(x))
|
262
|
+
for i in reader:
|
263
|
+
print(i)
|
264
|
+
|
265
|
+
print("证明不会修改外部对象")
|
266
|
+
print(file_obj.read())
|
267
|
+
|
268
|
+
del reader
|
@@ -49,7 +49,7 @@ if __name__ == '__main__':
|
|
49
49
|
print(reader.read([3, 3]).shape)
|
50
50
|
print(reader.find(1))
|
51
51
|
|
52
|
-
reader = UReader(file_path="test_data.txt", chunk_size=2, folder_path="./temp/233")
|
52
|
+
reader = UReader(file_path="test/test_data/test_data.txt", chunk_size=2, folder_path="./temp/233")
|
53
53
|
|
54
54
|
print(reader.read(2, 7))
|
55
55
|
# del reader
|
@@ -67,7 +67,7 @@ if __name__ == '__main__':
|
|
67
67
|
|
68
68
|
print(reader.find('data/6/horse_race_pan/2132020102319002000161_43_4.bmp'))
|
69
69
|
|
70
|
-
reader = Reader_for_files(file_path="test_data.txt", chunk_size=2, pre_jump_size=2, jump_size=2)
|
70
|
+
reader = Reader_for_files(file_path="test/test_data/test_data.txt", chunk_size=2, pre_jump_size=2, jump_size=2)
|
71
71
|
|
72
72
|
for i in reader:
|
73
73
|
print(2333, i)
|
@@ -2,6 +2,6 @@ from .convert_dict_key_to_number import convert_dict_key_to_number
|
|
2
2
|
from .convert_ndarray_to_list import convert_ndarray_to_list
|
3
3
|
from .escape_non_str_dict_key import escape_non_str_dict_key
|
4
4
|
from .unescape_non_str_dict_key import unescape_non_str_dict_key
|
5
|
-
from .
|
6
|
-
from .
|
5
|
+
from .escape_tuple_and_set import escape_tuple_and_set
|
6
|
+
from .unescape_tuple_and_set import unescape_tuple_and_set
|
7
7
|
from .integrate import integrate
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def escape_tuple_and_set(x):
|
2
|
+
"""
|
3
|
+
将 tuple 和 set 进行转义
|
4
|
+
转义: x ==> f"<eval>{x}"
|
5
|
+
反转义: f"<eval>{x}" ==> x
|
6
|
+
|
7
|
+
为什么要进行转义?
|
8
|
+
由于 json 中会将 tuple 作为 list 进行保存,同时也无法保存 set,因此在保存过程中会丢失相应信息。
|
9
|
+
"""
|
10
|
+
if isinstance(x, (tuple, set,)) or (isinstance(x, (str,)) and x.startswith("<eval>")):
|
11
|
+
return f'<eval>{x}'
|
12
|
+
else:
|
13
|
+
return x
|
14
|
+
|
15
|
+
|
16
|
+
if __name__ == '__main__':
|
17
|
+
print(escape_tuple_and_set((1, 2, "\'1\'")))
|
18
|
+
# <eval>(1, 2, "'1'")
|
19
|
+
print(escape_tuple_and_set({"1", (1, 2, 3), 233}))
|
20
|
+
# <eval>{'1', 233, (1, 2, 3)}
|
21
|
+
|
22
|
+
print(escape_tuple_and_set("<eval>233"))
|
23
|
+
# <eval><eval>233
|
kevin_toolbox/data_flow/file/json_/converter/{unescape_tuple.py → unescape_tuple_and_set.py}
RENAMED
@@ -1,11 +1,11 @@
|
|
1
|
-
def
|
1
|
+
def unescape_tuple_and_set(x):
|
2
2
|
"""
|
3
|
-
将 tuple 进行反转义
|
3
|
+
将 tuple 和 set 进行反转义
|
4
4
|
转义: x ==> f"<eval>{x}"
|
5
5
|
反转义: f"<eval>{x}" ==> x
|
6
6
|
|
7
7
|
为什么要进行转义?
|
8
|
-
由于 json 中会将 tuple 作为 list
|
8
|
+
由于 json 中会将 tuple 作为 list 进行保存,同时也无法保存 set,因此在保存过程中会丢失相应信息。
|
9
9
|
"""
|
10
10
|
if isinstance(x, str) and x.startswith("<eval>"):
|
11
11
|
x = x[6:]
|
@@ -17,7 +17,9 @@ def unescape_tuple(x):
|
|
17
17
|
|
18
18
|
|
19
19
|
if __name__ == '__main__':
|
20
|
-
print(
|
20
|
+
print(unescape_tuple_and_set("<eval>(1, 2, \"'1'\")"))
|
21
21
|
# (1, 2, "\'1\'")
|
22
|
-
print(
|
22
|
+
print(unescape_tuple_and_set("<eval>{'1', 233, (1, 2, 3)}"))
|
23
|
+
# {'1', 233, (1, 2, 3)}
|
24
|
+
print(unescape_tuple_and_set("<eval><eval>233"))
|
23
25
|
# "<eval>233"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
import json
|
3
|
-
from kevin_toolbox.data_flow.file.json_.converter import integrate,
|
3
|
+
from kevin_toolbox.data_flow.file.json_.converter import integrate, unescape_tuple_and_set, unescape_non_str_dict_key
|
4
4
|
from kevin_toolbox.nested_dict_list import traverse
|
5
5
|
|
6
6
|
|
@@ -14,14 +14,14 @@ def read_json(file_path, converters=None, b_use_suggested_converter=False):
|
|
14
14
|
转换器 converter 应该是一个形如 def(x): ... ; return x 的函数,具体可以参考
|
15
15
|
json_.converter 中已实现的转换器
|
16
16
|
b_use_suggested_converter: <boolean> 是否使用建议的转换器
|
17
|
-
建议使用 unescape/escape_non_str_dict_key 和 unescape/
|
17
|
+
建议使用 unescape/escape_non_str_dict_key 和 unescape/escape_tuple_and_set 这两对转换器,
|
18
18
|
可以避免因 json 的读取/写入而丢失部分信息。
|
19
19
|
默认为 False。
|
20
20
|
注意:当 converters 非 None,此参数失效,以 converters 中的具体设置为准
|
21
21
|
"""
|
22
22
|
assert os.path.isfile(file_path), f'file {file_path} not found'
|
23
23
|
if converters is None and b_use_suggested_converter:
|
24
|
-
converters = [
|
24
|
+
converters = [unescape_tuple_and_set, unescape_non_str_dict_key]
|
25
25
|
|
26
26
|
with open(file_path, 'r') as f:
|
27
27
|
content = json.load(f)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
import json
|
3
3
|
import copy
|
4
|
-
from kevin_toolbox.data_flow.file.json_.converter import integrate,
|
4
|
+
from kevin_toolbox.data_flow.file.json_.converter import integrate, escape_tuple_and_set, escape_non_str_dict_key
|
5
5
|
from kevin_toolbox.nested_dict_list import traverse
|
6
6
|
|
7
7
|
|
@@ -18,7 +18,7 @@ def write_json(content, file_path, sort_keys=False, converters=None, b_use_sugge
|
|
18
18
|
转换器 converter 应该是一个形如 def(x): ... ; return x 的函数,具体可以参考
|
19
19
|
json_.converter 中已实现的转换器
|
20
20
|
b_use_suggested_converter: <boolean> 是否使用建议的转换器
|
21
|
-
建议使用 unescape/escape_non_str_dict_key 和 unescape/
|
21
|
+
建议使用 unescape/escape_non_str_dict_key 和 unescape/escape_tuple_and_set 这两对转换器,
|
22
22
|
可以避免因 json 的读取/写入而丢失部分信息。
|
23
23
|
默认为 False。
|
24
24
|
注意:当 converters 非 None,此参数失效,以 converters 中的具体设置为准
|
@@ -26,7 +26,7 @@ def write_json(content, file_path, sort_keys=False, converters=None, b_use_sugge
|
|
26
26
|
assert isinstance(file_path, (str, type(None)))
|
27
27
|
|
28
28
|
if converters is None and b_use_suggested_converter:
|
29
|
-
converters = [
|
29
|
+
converters = [escape_tuple_and_set, escape_non_str_dict_key]
|
30
30
|
|
31
31
|
if converters is not None:
|
32
32
|
converter = integrate(converters)
|
@@ -15,6 +15,8 @@ class Kevin_Notation_Reader:
|
|
15
15
|
|
16
16
|
必要参数:
|
17
17
|
file_path: <string> 文件路径
|
18
|
+
file_obj: <file object> 文件对象
|
19
|
+
以上参数2选一,具体参见 File_Iterative_Reader
|
18
20
|
读取相关参数:
|
19
21
|
chunk_size: <integer> 每次读取多少行数据
|
20
22
|
beg: <integer> 开始读取的位置
|
@@ -28,6 +30,7 @@ class Kevin_Notation_Reader:
|
|
28
30
|
paras = {
|
29
31
|
# 必要参数
|
30
32
|
"file_path": None,
|
33
|
+
"file_obj": None,
|
31
34
|
# 读取相关参数
|
32
35
|
"chunk_size": 100,
|
33
36
|
"beg": 0,
|
@@ -38,9 +41,7 @@ class Kevin_Notation_Reader:
|
|
38
41
|
paras.update(kwargs)
|
39
42
|
|
40
43
|
# 校验参数
|
41
|
-
|
42
|
-
f'file not exists :{paras["file_path"]}'
|
43
|
-
#
|
44
|
+
# file_path 和 file_obj 交给 File_Iterative_Reader 校验
|
44
45
|
assert isinstance(paras["chunk_size"], (int,)) and (paras["chunk_size"] > 0 or paras["chunk_size"] == -1)
|
45
46
|
assert isinstance(paras["beg"], (int,)) and paras["beg"] >= 0
|
46
47
|
assert isinstance(paras["converter"], (Converter, dict,))
|
@@ -48,7 +49,7 @@ class Kevin_Notation_Reader:
|
|
48
49
|
self.paras = paras
|
49
50
|
|
50
51
|
# 读取开头
|
51
|
-
self.reader = File_Iterative_Reader(file_path=self.paras["file_path"],
|
52
|
+
self.reader = File_Iterative_Reader(file_path=self.paras["file_path"], file_obj=self.paras["file_obj"],
|
52
53
|
pre_jump_size=self.paras["beg"],
|
53
54
|
filter_=lambda x: x != "\n" and not x.startswith("//"), # 去除注释
|
54
55
|
map_func=lambda x: x.rsplit("\n", 1)[0].split("//", 1)[0],
|
@@ -64,7 +65,7 @@ class Kevin_Notation_Reader:
|
|
64
65
|
del self.reader
|
65
66
|
|
66
67
|
# 读取内容
|
67
|
-
self.reader = File_Iterative_Reader(file_path=self.paras["file_path"],
|
68
|
+
self.reader = File_Iterative_Reader(file_path=self.paras["file_path"], file_obj=self.paras["file_obj"],
|
68
69
|
pre_jump_size=self.paras["beg"] + offset,
|
69
70
|
filter_=lambda x: x != "\n" and not x.startswith("//"), # 去除注释
|
70
71
|
map_func=lambda x: x.rsplit("\n", 1)[0].split("//", 1)[0],
|
@@ -1,11 +1,13 @@
|
|
1
1
|
from kevin_toolbox.data_flow.file import kevin_notation
|
2
2
|
|
3
3
|
|
4
|
-
def read(file_path):
|
4
|
+
def read(file_path=None, file_obj=None):
|
5
5
|
"""
|
6
6
|
读取整个文件的快捷接口
|
7
7
|
"""
|
8
|
-
|
8
|
+
assert file_path is not None or file_obj is not None
|
9
|
+
|
10
|
+
with kevin_notation.Reader(file_path=file_path, chunk_size=-1, file_obj=file_obj) as reader:
|
9
11
|
# metadata
|
10
12
|
metadata = reader.metadata
|
11
13
|
# content
|
@@ -134,11 +134,23 @@ def test_writer_1(expected_metadata, expected_content, file_path):
|
|
134
134
|
zip(metadata_ls, content_ls, file_path_ls))
|
135
135
|
def test_read(expected_metadata, expected_content, file_path):
|
136
136
|
print("test read()")
|
137
|
-
# 读取
|
137
|
+
# 使用 file_path 读取
|
138
138
|
metadata, content = kevin_notation.read(file_path=file_path)
|
139
|
+
|
140
|
+
# 使用 file_obj 读取
|
141
|
+
file_obj = open(file_path, "r")
|
142
|
+
metadata_1, content_1 = kevin_notation.read(file_obj=file_obj)
|
143
|
+
assert len(file_obj.read()) > 0 # 不影响输入的 file_obj
|
144
|
+
|
145
|
+
# 使用字符串构造 file_obj 读取
|
146
|
+
from io import StringIO
|
147
|
+
file_obj = StringIO(initial_value=open(file_path, "r").read())
|
148
|
+
metadata_2, content_2 = kevin_notation.read(file_obj=file_obj)
|
149
|
+
assert len(file_obj.read()) > 0
|
150
|
+
|
139
151
|
# 检验
|
140
|
-
check_consistency(expected_metadata, metadata)
|
141
|
-
check_consistency(expected_content, content)
|
152
|
+
check_consistency(expected_metadata, metadata, metadata_1, metadata_2)
|
153
|
+
check_consistency(expected_content, content, content_1, content_2)
|
142
154
|
|
143
155
|
|
144
156
|
@pytest.mark.parametrize("expected_metadata, expected_content, file_path",
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from kevin_toolbox.math.utils import
|
1
|
+
from kevin_toolbox.math.utils import split_integer_most_evenly
|
2
2
|
|
3
3
|
|
4
4
|
def generate_table(content_s, orientation="vertical", chunk_nums=None, chunk_size=None, b_allow_misaligned_values=False,
|
@@ -60,7 +60,7 @@ def generate_table(content_s, orientation="vertical", chunk_nums=None, chunk_siz
|
|
60
60
|
# 按照 chunk_nums 或者 chunk_size 对表格进行分割
|
61
61
|
if chunk_nums is not None or chunk_size is not None:
|
62
62
|
if chunk_nums is not None:
|
63
|
-
split_len_ls =
|
63
|
+
split_len_ls = split_integer_most_evenly(x=max_length, group_nums=chunk_nums)
|
64
64
|
else:
|
65
65
|
split_len_ls = [chunk_size] * (max_length // chunk_size)
|
66
66
|
if max_length % chunk_size != 0:
|
@@ -2,4 +2,4 @@ from .get_function_table_for_array_and_tensor import get_function_table_for_arra
|
|
2
2
|
from .convert_dtype import convert_dtype
|
3
3
|
from .get_crop_by_box import get_crop_by_box
|
4
4
|
from .set_crop_by_box import set_crop_by_box
|
5
|
-
from .
|
5
|
+
from .split_integer_most_evenly import split_integer_most_evenly
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import numpy as np
|
2
2
|
|
3
3
|
|
4
|
-
def
|
4
|
+
def split_integer_most_evenly(x, group_nums):
|
5
5
|
assert isinstance(x, (int, np.integer,)) and x >= 0 and group_nums > 0
|
6
6
|
|
7
7
|
res = np.ones(group_nums, dtype=int) * (x // group_nums)
|
@@ -10,4 +10,4 @@ def spilt_integer_most_evenly(x, group_nums):
|
|
10
10
|
|
11
11
|
|
12
12
|
if __name__ == '__main__':
|
13
|
-
print(
|
13
|
+
print(split_integer_most_evenly(x=100, group_nums=7))
|
@@ -29,13 +29,15 @@ def read(input_path, **kwargs):
|
|
29
29
|
|
30
30
|
# 读取 var
|
31
31
|
var = json_.read(file_path=os.path.join(input_path, "var.json"), b_use_suggested_converter=True)
|
32
|
+
# 读取 record
|
33
|
+
record_s = dict()
|
34
|
+
if os.path.isfile(os.path.join(input_path, "record.json")):
|
35
|
+
record_s = json_.read(file_path=os.path.join(input_path, "record.json"), b_use_suggested_converter=True)
|
32
36
|
|
33
37
|
# 读取被处理的节点
|
34
38
|
processed_nodes = []
|
35
|
-
if
|
36
|
-
for name, value in ndl.get_nodes(
|
37
|
-
var=json_.read(file_path=os.path.join(input_path, "record.json"),
|
38
|
-
b_use_suggested_converter=True)["processed"], level=-1, b_strict=True):
|
39
|
+
if record_s:
|
40
|
+
for name, value in ndl.get_nodes(var=record_s["processed"], level=-1, b_strict=True):
|
39
41
|
if value:
|
40
42
|
processed_nodes.append(name)
|
41
43
|
else:
|
@@ -56,6 +58,11 @@ def read(input_path, **kwargs):
|
|
56
58
|
bk = SERIALIZER_BACKEND.get(name=value.pop("backend"))(folder=os.path.join(input_path, "nodes"))
|
57
59
|
ndl.set_value(var=var, name=name, value=bk.read(**value))
|
58
60
|
|
61
|
+
#
|
62
|
+
if record_s.get("b_keep_identical_relations", False):
|
63
|
+
from kevin_toolbox.nested_dict_list import value_parser
|
64
|
+
var = value_parser.replace_identical_with_reference(var=var, flag="same", b_reverse=True)
|
65
|
+
|
59
66
|
#
|
60
67
|
if temp_dir is not None:
|
61
68
|
for_os.remove(path=temp_dir, ignore_errors=True)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Saved_Node_Name_Builder:
|
2
|
+
"""
|
3
|
+
生成保存节点内容时的文件夹/文件名称
|
4
|
+
"""
|
5
|
+
|
6
|
+
def __init__(self, format_):
|
7
|
+
try:
|
8
|
+
temp = format_.format(**{k: k + "_" * 3 for k in {"raw_name", "id", "hash_name", "count"}})
|
9
|
+
assert len(temp) > len(format_)
|
10
|
+
except:
|
11
|
+
raise ValueError(f'invalid saved_node_name_format {format_}')
|
12
|
+
|
13
|
+
self.format_ = format_
|
14
|
+
self.count = 0
|
15
|
+
|
16
|
+
def __call__(self, name, value):
|
17
|
+
from kevin_toolbox.nested_dict_list import get_hash
|
18
|
+
|
19
|
+
res = self.format_.format(
|
20
|
+
**{"raw_name": name, "id": id(value), "hash_name": get_hash(name, length=12), "count": self.count})
|
21
|
+
self.count += 1
|
22
|
+
return res
|
23
|
+
|
24
|
+
|
25
|
+
if __name__ == '__main__':
|
26
|
+
bd = Saved_Node_Name_Builder(format_="{raw_name}_{count}_{hash_name}_{id}")
|
27
|
+
print(bd(":a@0", 1))
|
28
|
+
print(bd(":b:c", []))
|
29
|
+
|
30
|
+
# bd = Saved_Node_Name_Builder(format_="")
|
31
|
+
# bd = Saved_Node_Name_Builder(format_="{raw_name2}_{count}")
|
@@ -7,16 +7,18 @@ from kevin_toolbox.patches import for_os
|
|
7
7
|
import kevin_toolbox.nested_dict_list as ndl
|
8
8
|
from kevin_toolbox.nested_dict_list.traverse import Traversal_Mode
|
9
9
|
from .enum_variable import Strictness_Level
|
10
|
+
from .saved_node_name_builder import Saved_Node_Name_Builder
|
10
11
|
|
11
12
|
|
12
13
|
def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_pack_into_tar=True,
|
13
|
-
strictness_level=Strictness_Level.COMPATIBLE,
|
14
|
+
strictness_level=Strictness_Level.COMPATIBLE, saved_node_name_format='{count}_{hash_name}',
|
15
|
+
b_keep_identical_relations=False, **kwargs):
|
14
16
|
"""
|
15
17
|
将输入的嵌套字典列表 var 的结构和节点值保存到文件中
|
16
18
|
遍历 var,匹配并使用 settings 中设置的保存方式来对各部分结构/节点进行序列化
|
17
19
|
将会生成一个文件夹或者 .tar 文件,其中包含:
|
18
20
|
- var.json: 用于保存结构、简单节点值、复杂节点值/结构的序列化方式
|
19
|
-
- nodes
|
21
|
+
- nodes/: 该目录中包含一系列 <name>.<suffix> 文件或者 <name> 文件夹,其中包含复杂节点值/结构的序列化结果
|
20
22
|
- record.json: 其中记录了:
|
21
23
|
{
|
22
24
|
"processed": ... # 对哪些节点/部分进行了处理
|
@@ -82,25 +84,50 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
|
|
82
84
|
- "low" / Strictness_Level.IGNORE_FAILURE 匹配不完整,或者某些节点尝试过所有匹配到
|
83
85
|
的 backend 之后仍然无法写入
|
84
86
|
默认是 "normal"
|
87
|
+
saved_node_name_format: <str> nodes/目录下节点文件/文件夹的命名方式。
|
88
|
+
基本结构为: '{<part_0>}...{<part_1>}...'
|
89
|
+
其中 {} 内将根据 part 指定的类型进行自动填充。目前支持以下几种选项:
|
90
|
+
- "raw_name" 该节点对应位置的 name。
|
91
|
+
- "id" 该节点在当前内存中的 id。
|
92
|
+
- "hash_name" 该节点位置 name 的 hash 值。
|
93
|
+
- "count" 累加计算,表示是保存的第几个节点。
|
94
|
+
!!注意:
|
95
|
+
"raw_name" 该选项在 v1.3.3 前被使用,但是由于其可能含有 : 和 / 等特殊符号,当以其作为文件夹名时,
|
96
|
+
可能会引发错误。因此对于 windows 用户,禁止使用该选项,对于 mac 和 linux 用户,同样也不建议使用该选项。
|
97
|
+
"id" 虽然具有唯一性,但是其值对于每次运行是随机的。
|
98
|
+
"hash_name" 有极低的可能会发生 hash 碰撞。
|
99
|
+
综合而言:
|
100
|
+
建议使用 "hash_name" 和 "count" 的组合。
|
101
|
+
默认值为:
|
102
|
+
'{count}_{hash_name}'
|
103
|
+
b_keep_identical_relations: <boolean> 是否保留不同节点之间的 id 相等关系。
|
104
|
+
具体而言,就是使用 value_parser.replace_identical_with_reference() 函数将具有相同 id 的多个节点,
|
105
|
+
替换为单个节点和其多个引用的形式。
|
106
|
+
对于 ndl 中存在大量具有相同 id 的重复节点的情况,使用该操作可以额外达到压缩的效果。
|
107
|
+
默认为 False
|
85
108
|
"""
|
86
109
|
from kevin_toolbox.nested_dict_list.serializer.variable import SERIALIZER_BACKEND
|
87
110
|
|
88
|
-
#
|
111
|
+
# 检查参数
|
89
112
|
traversal_mode = Traversal_Mode(traversal_mode)
|
90
113
|
strictness_level = Strictness_Level(strictness_level)
|
91
114
|
os.makedirs(output_dir, exist_ok=True)
|
92
115
|
var = ndl.copy_(var=var, b_deepcopy=False)
|
116
|
+
if b_keep_identical_relations:
|
117
|
+
from kevin_toolbox.nested_dict_list import value_parser
|
118
|
+
var = value_parser.replace_identical_with_reference(var=var, flag="same", b_reverse=False)
|
93
119
|
if settings is None:
|
94
120
|
settings = [{"match_cond": "<level>-1", "backend": (":skip:simple", ":numpy:npy", ":torch:tensor", ":pickle")}]
|
121
|
+
snn_builder = Saved_Node_Name_Builder(format_=saved_node_name_format)
|
95
122
|
|
96
123
|
# 构建 processed_s
|
97
124
|
# 为了避免重复处理节点/结构,首先构建与 var 具有相似结构的 processed_s 来记录处理处理进度。
|
98
125
|
# 对于 processed_s,其节点值为 True 时表示该节点已经被处理,当节点值为 False 或者 list/dict 类型时表示该节点或者节点下面的结构中仍然
|
99
126
|
# 存在未处理的部分。
|
100
127
|
# 对于中间节点,只有其下所有叶节点都未处理时才会被匹配。
|
101
|
-
processed_s =
|
128
|
+
processed_s = ndl.copy_(var=var, b_deepcopy=False, b_keep_internal_references=False)
|
102
129
|
for n, _ in ndl.get_nodes(var=var, level=-1, b_strict=True):
|
103
|
-
ndl.set_value(var=processed_s, name=n, value=False, b_force=
|
130
|
+
ndl.set_value(var=processed_s, name=n, value=False, b_force=False)
|
104
131
|
# processed_s_bak 用于记录 var 的原始结构
|
105
132
|
processed_s_bak = ndl.copy_(var=processed_s, b_deepcopy=True)
|
106
133
|
if "_hook_for_debug" in kwargs:
|
@@ -126,27 +153,21 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
|
|
126
153
|
_process = _process_from_top_to_down
|
127
154
|
else:
|
128
155
|
_process = _process_from_down_to_top
|
129
|
-
paras = dict(
|
130
|
-
var=var, processed_s=processed_s, match_cond=setting["match_cond"],
|
131
|
-
traversal_mode=t_mode, strictness_level=strictness_level
|
132
|
-
)
|
156
|
+
paras = dict(var=var, match_cond=setting["match_cond"], traversal_mode=t_mode)
|
133
157
|
elif setting["match_cond"].startswith("<level>"):
|
134
158
|
_process = _process_for_level
|
135
|
-
paras = dict(
|
136
|
-
var=var, processed_s=processed_s, processed_s_bak=processed_s_bak,
|
137
|
-
level=int(setting["match_cond"][7:]), strictness_level=strictness_level
|
138
|
-
)
|
159
|
+
paras = dict(var=var, processed_s_bak=processed_s_bak, level=int(setting["match_cond"][7:]))
|
139
160
|
elif setting["match_cond"].startswith("<node>"):
|
140
161
|
_process = _process_for_name
|
141
|
-
paras = dict(var=var,
|
142
|
-
strictness_level=strictness_level)
|
162
|
+
paras = dict(var=var, name=setting["match_cond"][6:])
|
143
163
|
else:
|
144
164
|
raise ValueError(f'invalid match_cond: {setting["match_cond"]}')
|
145
165
|
# 执行
|
146
166
|
for i in backend_name_ls:
|
147
167
|
# print(processed_s)
|
148
168
|
# print(f'backend: {i}')
|
149
|
-
_process(backend=backend_s[i],
|
169
|
+
_process(backend=backend_s[i], strictness_level=strictness_level, processed_s=processed_s,
|
170
|
+
snn_builder=snn_builder, **paras)
|
150
171
|
if "_hook_for_debug" in kwargs:
|
151
172
|
kwargs["_hook_for_debug"]["processed"].append([i, ndl.copy_(var=processed_s, b_deepcopy=True)])
|
152
173
|
|
@@ -171,7 +192,8 @@ def write(var, output_dir, settings=None, traversal_mode=Traversal_Mode.BFS, b_p
|
|
171
192
|
json_.write(content=var, file_path=os.path.join(output_dir, "var.json"), b_use_suggested_converter=True)
|
172
193
|
# 保存处理结果(非必要)
|
173
194
|
json_.write(content=dict(processed=processed_s, raw_structure=processed_s_bak, timestamp=time.time(),
|
174
|
-
kt_version=kevin_toolbox.__version__
|
195
|
+
kt_version=kevin_toolbox.__version__,
|
196
|
+
b_keep_identical_relations=b_keep_identical_relations),
|
175
197
|
file_path=os.path.join(output_dir, "record.json"), b_use_suggested_converter=True)
|
176
198
|
|
177
199
|
# 打包成 .tar 文件
|
@@ -196,13 +218,13 @@ def _judge_processed_or_not(processed_s, name):
|
|
196
218
|
return b_processed
|
197
219
|
|
198
220
|
|
199
|
-
def _process_for_level(var, processed_s, processed_s_bak, level, backend, strictness_level):
|
221
|
+
def _process_for_level(var, processed_s, processed_s_bak, level, backend, strictness_level, snn_builder):
|
200
222
|
for name, _ in ndl.get_nodes(var=processed_s_bak, level=level, b_strict=True):
|
201
223
|
_process_for_name(var=var, processed_s=processed_s, name=name, backend=backend,
|
202
|
-
strictness_level=strictness_level)
|
224
|
+
strictness_level=strictness_level, snn_builder=snn_builder)
|
203
225
|
|
204
226
|
|
205
|
-
def _process_for_name(var, processed_s, name, backend, strictness_level):
|
227
|
+
def _process_for_name(var, processed_s, name, backend, strictness_level, snn_builder):
|
206
228
|
if _judge_processed_or_not(processed_s=processed_s, name=name) is True:
|
207
229
|
# has been processed
|
208
230
|
return
|
@@ -212,8 +234,9 @@ def _process_for_name(var, processed_s, name, backend, strictness_level):
|
|
212
234
|
return
|
213
235
|
|
214
236
|
# write by backend
|
237
|
+
snn_name = snn_builder(name=name, value=value)
|
215
238
|
try:
|
216
|
-
res = backend.write(name=
|
239
|
+
res = backend.write(name=snn_name, var=value)
|
217
240
|
except:
|
218
241
|
assert strictness_level in (Strictness_Level.IGNORE_FAILURE, Strictness_Level.COMPATIBLE), \
|
219
242
|
f'An error occurred when node {name} was saved using the first matched backend {backend}'
|
@@ -222,7 +245,7 @@ def _process_for_name(var, processed_s, name, backend, strictness_level):
|
|
222
245
|
ndl.set_value(var=var, name=name, value=res, b_force=False)
|
223
246
|
|
224
247
|
|
225
|
-
def _process_from_top_to_down(var, processed_s, match_cond, backend, traversal_mode, strictness_level):
|
248
|
+
def _process_from_top_to_down(var, processed_s, match_cond, backend, traversal_mode, strictness_level, snn_builder):
|
226
249
|
def match_cond_(parent_type, idx, value):
|
227
250
|
nonlocal match_cond, processed_s
|
228
251
|
|
@@ -237,8 +260,9 @@ def _process_from_top_to_down(var, processed_s, match_cond, backend, traversal_m
|
|
237
260
|
nonlocal processed_s, backend, strictness_level
|
238
261
|
|
239
262
|
# write by backend
|
263
|
+
snn_name = snn_builder(name=idx, value=value)
|
240
264
|
try:
|
241
|
-
res = backend.write(name=
|
265
|
+
res = backend.write(name=snn_name, var=value)
|
242
266
|
except:
|
243
267
|
assert strictness_level in (Strictness_Level.IGNORE_FAILURE, Strictness_Level.COMPATIBLE), \
|
244
268
|
f'An error occurred when node {name} was saved using the first matched backend {backend}'
|
@@ -250,7 +274,7 @@ def _process_from_top_to_down(var, processed_s, match_cond, backend, traversal_m
|
|
250
274
|
b_use_name_as_idx=True, traversal_mode=traversal_mode, b_traverse_matched_element=False)
|
251
275
|
|
252
276
|
|
253
|
-
def _process_from_down_to_top(var, processed_s, match_cond, backend, traversal_mode, strictness_level):
|
277
|
+
def _process_from_down_to_top(var, processed_s, match_cond, backend, traversal_mode, strictness_level, snn_builder):
|
254
278
|
processed_s_raw, processed_s = processed_s, ndl.copy_(var=processed_s, b_deepcopy=True)
|
255
279
|
|
256
280
|
def match_cond_(parent_type, idx, value):
|
@@ -268,8 +292,9 @@ def _process_from_down_to_top(var, processed_s, match_cond, backend, traversal_m
|
|
268
292
|
nonlocal processed_s, backend, processed_s_raw, strictness_level
|
269
293
|
|
270
294
|
# write by backend
|
295
|
+
snn_name = snn_builder(name=idx, value=value)
|
271
296
|
try:
|
272
|
-
res = backend.write(name=
|
297
|
+
res = backend.write(name=snn_name, var=value)
|
273
298
|
except:
|
274
299
|
assert strictness_level in (Strictness_Level.IGNORE_FAILURE, Strictness_Level.COMPATIBLE), \
|
275
300
|
f'An error occurred when node {name} was saved using the first matched backend {backend}'
|
@@ -305,7 +330,7 @@ if __name__ == '__main__':
|
|
305
330
|
{"match_cond": lambda _, __, value: not isinstance(value, (list, dict)),
|
306
331
|
"backend": (":skip:simple",)},
|
307
332
|
]
|
308
|
-
write(var=var_, output_dir=os.path.join(os.path.dirname(__file__), "
|
333
|
+
write(var=var_, output_dir=os.path.join(os.path.dirname(__file__), "temp"), traversal_mode="bfs",
|
309
334
|
b_pack_into_tar=True, settings=settings_, _hook_for_debug=_hook_for_debug)
|
310
335
|
|
311
336
|
for bk_name, p in _hook_for_debug["processed"]:
|
@@ -2,3 +2,4 @@ from .cal_relation_between_references import cal_relation_between_references
|
|
2
2
|
from .eval_references import eval_references
|
3
3
|
from .parse_references import parse_references
|
4
4
|
from .parse_and_eval_references import parse_and_eval_references
|
5
|
+
from .replace_identical_with_reference import replace_identical_with_reference
|
@@ -0,0 +1,127 @@
|
|
1
|
+
from collections import defaultdict
|
2
|
+
from kevin_toolbox.nested_dict_list import get_nodes, get_value, set_value
|
3
|
+
from kevin_toolbox.nested_dict_list import value_parser
|
4
|
+
|
5
|
+
|
6
|
+
def replace_identical_with_reference(var, flag="same", match_cond=None, b_reverse=False):
|
7
|
+
"""
|
8
|
+
将具有相同 id 的多个节点,替换为单个节点和其多个引用的形式
|
9
|
+
一般用于去除冗余部分,压缩 ndl 的结构
|
10
|
+
|
11
|
+
参数:
|
12
|
+
var:
|
13
|
+
flag: <str> 引用标记头,表示该节点应该替换为指定节点的内容
|
14
|
+
默认为 "same"
|
15
|
+
注意,在正向过程中,如果遇到本身就是以该 flag 开头的字符串,会自动在前添加多一个 flag 以示区分,
|
16
|
+
然后在逆向过程中,遇到两个 flag 标记开头的字符串将删除一个,然后跳过不处理。
|
17
|
+
match_cond: <func> 仅对匹配上(返回True视为匹配上)的节点进行处理
|
18
|
+
函数类型为 def(name, value)
|
19
|
+
其中:
|
20
|
+
name 该节点在结构体中的位置
|
21
|
+
value 节点的值
|
22
|
+
默认不对 int、float、bool、str、None 等类型进行处理
|
23
|
+
b_reverse: <boolean> 是否进行逆向操作
|
24
|
+
"""
|
25
|
+
if match_cond is None:
|
26
|
+
match_cond = lambda name, value: not isinstance(value, (int, float, bool, str, type(None)))
|
27
|
+
assert callable(match_cond)
|
28
|
+
|
29
|
+
if b_reverse:
|
30
|
+
return _reverse(var, flag)
|
31
|
+
else:
|
32
|
+
return _forward(var, flag, match_cond)
|
33
|
+
|
34
|
+
|
35
|
+
def _forward(var, flag, match_cond):
|
36
|
+
id_to_height_s = defaultdict(set)
|
37
|
+
id_to_name_s = defaultdict(set)
|
38
|
+
height = 1
|
39
|
+
while True:
|
40
|
+
node_ls = get_nodes(var=var, level=-height, b_strict=True)
|
41
|
+
if not node_ls:
|
42
|
+
break
|
43
|
+
for name, value in node_ls:
|
44
|
+
if not match_cond(name, value):
|
45
|
+
continue
|
46
|
+
id_to_name_s[id(value)].add(name)
|
47
|
+
id_to_height_s[id(value)].add(height)
|
48
|
+
height += 1
|
49
|
+
|
50
|
+
#
|
51
|
+
for k, v in list(id_to_height_s.items()):
|
52
|
+
# 仅保留有多个节点对应的 id
|
53
|
+
if len(id_to_name_s[k]) <= 1:
|
54
|
+
id_to_height_s.pop(k)
|
55
|
+
id_to_name_s.pop(k)
|
56
|
+
continue
|
57
|
+
# 具有相同 id 的节点所处的高度应该相同
|
58
|
+
assert len(v) == 1, f'nodes {id_to_name_s[k]} have different heights: {v}'
|
59
|
+
# 按高度排序
|
60
|
+
id_vs_height = sorted([(k, v.pop()) for k, v in id_to_height_s.items()], key=lambda x: x[1], reverse=True)
|
61
|
+
|
62
|
+
# 从高到低,依次将具有相同 id 的节点替换为 单个节点和多个引用 的形式
|
63
|
+
temp = []
|
64
|
+
processed_name_set = set()
|
65
|
+
for k, _ in id_vs_height:
|
66
|
+
# 找出父节点仍然未被处理的节点(亦即仍然能够访问到的节点)
|
67
|
+
unprocessed_name_set = {n for n in id_to_name_s[k] if id(get_value(var=var, name=n, default=temp)) == k}
|
68
|
+
if len(unprocessed_name_set) <= 1:
|
69
|
+
continue
|
70
|
+
# 任选其一进行保留,其余改为引用
|
71
|
+
keep_name = unprocessed_name_set.pop()
|
72
|
+
for name in unprocessed_name_set:
|
73
|
+
try:
|
74
|
+
var = set_value(var=var, name=name, value=f'<{flag}>{{{keep_name}}}', b_force=False)
|
75
|
+
except:
|
76
|
+
breakpoint()
|
77
|
+
processed_name_set.update(unprocessed_name_set)
|
78
|
+
|
79
|
+
# 将叶节点中,未被处理过,且是 str,且以 flag 开头的字符串,添加多一个 flag,以示区分
|
80
|
+
for name, value in get_nodes(var=var, level=-1, b_strict=True):
|
81
|
+
if name not in processed_name_set and isinstance(value, str) and value.startswith(f'<{flag}>'):
|
82
|
+
var = set_value(var=var, name=name, value=f'<{flag}>' + value, b_force=False)
|
83
|
+
|
84
|
+
return var
|
85
|
+
|
86
|
+
|
87
|
+
class _My_Str:
|
88
|
+
def __init__(self, s):
|
89
|
+
self.s = s
|
90
|
+
|
91
|
+
|
92
|
+
def _reverse(var, flag):
|
93
|
+
# 找出叶节点中,带有2个以上 flag 标记的字符串,删除其中一个标记,并使用 _My_Str 包裹,以便与普通引用节点区分
|
94
|
+
for name, value in get_nodes(var=var, level=-1, b_strict=True):
|
95
|
+
if isinstance(value, str) and value.startswith(f'<{flag}><{flag}>'):
|
96
|
+
var = set_value(var=var, name=name, value=_My_Str(value[len(flag) + 2:]), b_force=False)
|
97
|
+
# 解释引用
|
98
|
+
var, _ = value_parser.parse_and_eval_references(var=var, flag=flag)
|
99
|
+
# 解除 _My_Str 包裹
|
100
|
+
for name, value in get_nodes(var=var, level=-1, b_strict=True):
|
101
|
+
if isinstance(value, _My_Str):
|
102
|
+
var = set_value(var=var, name=name, value=value.s, b_force=False)
|
103
|
+
return var
|
104
|
+
|
105
|
+
|
106
|
+
if __name__ == '__main__':
|
107
|
+
import numpy as np
|
108
|
+
from kevin_toolbox.nested_dict_list import copy_
|
109
|
+
|
110
|
+
a = np.array([1, 2, 3])
|
111
|
+
b = np.ones((2, 3))
|
112
|
+
c = [a, b]
|
113
|
+
d = {"a": a, "b": b}
|
114
|
+
e = {"c1": c, "c2": c}
|
115
|
+
x = [e, a, d, c, "<same>{@1}", "<same><same>{@1}"]
|
116
|
+
|
117
|
+
print(x)
|
118
|
+
|
119
|
+
y = replace_identical_with_reference(var=copy_(x, b_deepcopy=True), flag="same")
|
120
|
+
print(y)
|
121
|
+
|
122
|
+
x1 = replace_identical_with_reference(var=y, flag="same", b_reverse=True)
|
123
|
+
print(x1)
|
124
|
+
|
125
|
+
from kevin_toolbox.patches.for_test import check_consistency
|
126
|
+
|
127
|
+
check_consistency(x, x1)
|
@@ -8,11 +8,57 @@ class DEFAULT_RNG:
|
|
8
8
|
for name in np.random.__all__:
|
9
9
|
setattr(DEFAULT_RNG, name, getattr(np.random, name))
|
10
10
|
|
11
|
+
func_map_s = {
|
12
|
+
'rand': lambda rng, *arg, **kwargs: rng.random(size=arg, **kwargs),
|
13
|
+
'randint': 'integers',
|
14
|
+
'randn': lambda rng, *arg, **kwargs: rng.normal(size=arg, **kwargs),
|
15
|
+
'random_integers': 'integers',
|
16
|
+
'random_sample': 'random',
|
17
|
+
'ranf': 'random'
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
class My_RNG:
|
22
|
+
def __init__(self, rng):
|
23
|
+
self._rng = rng
|
24
|
+
|
25
|
+
for name in np.random.__all__:
|
26
|
+
setattr(DEFAULT_RNG, name, getattr(np.random, name))
|
27
|
+
|
28
|
+
# self.key
|
29
|
+
def __getattr__(self, key):
|
30
|
+
if "_rng" not in self.__dict__:
|
31
|
+
# _rng 未被设置,未完成初始化。
|
32
|
+
return super().__getattr__(key)
|
33
|
+
else:
|
34
|
+
res = getattr(self._rng, key, None)
|
35
|
+
if res is None and key in func_map_s:
|
36
|
+
if callable(func_map_s[key]):
|
37
|
+
res = lambda *arg, **kwargs: func_map_s[key](self._rng, *arg, **kwargs)
|
38
|
+
else:
|
39
|
+
res = getattr(self._rng, func_map_s[key], None)
|
40
|
+
#
|
41
|
+
if res is None:
|
42
|
+
raise AttributeError(f"attribute '{key}' not found in {type(self)}")
|
43
|
+
else:
|
44
|
+
return res
|
45
|
+
|
11
46
|
|
12
47
|
def get_rng(seed=None, rng=None, **kwargs):
|
13
48
|
if seed is not None:
|
14
|
-
|
49
|
+
# 注意,随机生成器相较于 numpy.random 有部分属性缺失:
|
50
|
+
# ['get_state', 'rand', 'randint', 'randn', 'random_integers', 'random_sample', 'ranf', 'sample', 'seed',
|
51
|
+
# 'set_state', 'Generator', 'RandomState', 'SeedSequence', 'MT19937', 'Philox', 'PCG64', 'PCG64DXSM',
|
52
|
+
# 'SFC64', 'default_rng', 'BitGenerator']
|
53
|
+
rng = My_RNG(rng=np.random.default_rng(seed=seed))
|
15
54
|
if rng is not None:
|
16
55
|
return rng
|
17
56
|
else:
|
18
57
|
return DEFAULT_RNG
|
58
|
+
|
59
|
+
|
60
|
+
if __name__ == '__main__':
|
61
|
+
a = get_rng(seed=2)
|
62
|
+
|
63
|
+
# 尝试访问随机生成器中缺失的部分方法
|
64
|
+
print(a.randn(2, 3))
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: kevin-toolbox-dev
|
3
|
+
Version: 1.3.4
|
4
|
+
Summary: 一个常用的工具代码包集合
|
5
|
+
Home-page: https://github.com/cantbeblank96/kevin_toolbox
|
6
|
+
Download-URL: https://github.com/username/your-package/archive/refs/tags/v1.0.0.tar.gz
|
7
|
+
Author: kevin hsu
|
8
|
+
Author-email: xukaiming1996@163.com
|
9
|
+
License: MIT
|
10
|
+
Keywords: mathematics,pytorch,numpy,machine-learning,algorithm
|
11
|
+
Platform: UNKNOWN
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
13
|
+
Classifier: Programming Language :: Python
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
15
|
+
Requires-Python: >=3.6
|
16
|
+
Description-Content-Type: text/markdown
|
17
|
+
Requires-Dist: torch (>=1.2.0)
|
18
|
+
Requires-Dist: numpy (>=1.19.0)
|
19
|
+
Provides-Extra: plot
|
20
|
+
Requires-Dist: matplotlib (>=3.0) ; extra == 'plot'
|
21
|
+
Provides-Extra: rest
|
22
|
+
Requires-Dist: pytest (>=6.2.5) ; extra == 'rest'
|
23
|
+
Requires-Dist: line-profiler (>=3.5) ; extra == 'rest'
|
24
|
+
|
25
|
+
# kevin_toolbox
|
26
|
+
|
27
|
+
一个通用的工具代码包集合
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
环境要求
|
32
|
+
|
33
|
+
```shell
|
34
|
+
numpy>=1.19
|
35
|
+
pytorch>=1.2
|
36
|
+
```
|
37
|
+
|
38
|
+
安装方法:
|
39
|
+
|
40
|
+
```shell
|
41
|
+
pip install kevin-toolbox --no-dependencies
|
42
|
+
```
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
[项目地址 Repo](https://github.com/cantbeblank96/kevin_toolbox)
|
47
|
+
|
48
|
+
[使用指南 User_Guide](./notes/User_Guide.md)
|
49
|
+
|
50
|
+
[免责声明 Disclaimer](./notes/Disclaimer.md)
|
51
|
+
|
52
|
+
[版本更新记录](./notes/Release_Record.md):
|
53
|
+
|
54
|
+
- v 1.3.4 (2024-04-06)【bug fix】【new feature】
|
55
|
+
- nested_dict_list
|
56
|
+
- 【new feature】add replace_identical_with_reference() to value_parser,新增该函数用于将具有相同 id 的多个节点,替换为单个节点和其多个引用的形式。一般用于去除冗余部分,压缩 ndl 的结构。
|
57
|
+
- 【bug fix】【new feature】fix bug in write(),添加了 saved_node_name_format 参数控制 nodes 下文件名的生成。
|
58
|
+
- bug:在 v1.3.3 前直接使用原始的 node_name 来作为 nodes/ 目录下的文件名,这导致当 node_name 中带有特殊字符时,比如 "/"(在linux下) 和 ":"(在windows下),将会导致保存失败。
|
59
|
+
- fix:使用 saved_node_name_format 指定生成文件名的方式,默认方式 '{count}_{hash_name}' 可以避免出现特殊字符。
|
60
|
+
- 【bug fix】fix bug in write()
|
61
|
+
- bug:在 v1.3.3 前 processed_s 通过 ndl.set_value() 来逐个节点构建,但是由于根据节点名创建的结果可能和原结构存在差异(详见 ndl.set_value() 中b_force参数的介绍),因此导致 processed_s 和 var 结构不一致,导致出错。
|
62
|
+
- fix:使用 ndl.copy_() 来创建结构与 var 一致的 processed_s。
|
63
|
+
- 【new feature】add b_keep_identical_relations to write(),增加该参数用于决定是否保留不同节点之间的 id 相等关系。
|
64
|
+
- 添加了对应的测试用例。
|
65
|
+
|
66
|
+
|
67
|
+
|
@@ -1,4 +1,4 @@
|
|
1
|
-
kevin_toolbox/__init__.py,sha256=
|
1
|
+
kevin_toolbox/__init__.py,sha256=ryG5DAc-XozLnxNQjuTKTRynJFnwdQHKBZ2vaN1upx4,410
|
2
2
|
kevin_toolbox/computer_science/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
kevin_toolbox/computer_science/algorithm/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
4
4
|
kevin_toolbox/computer_science/algorithm/cache_manager/__init__.py,sha256=p2hddkZ1HfYF9-m2Hx-o9IotwQHd4QwDCePy2ADpTDA,41
|
@@ -66,29 +66,29 @@ kevin_toolbox/data_flow/core/cache/cache_manager_for_iterator.py,sha256=DqTNiZbn
|
|
66
66
|
kevin_toolbox/data_flow/core/cache/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
67
67
|
kevin_toolbox/data_flow/core/cache/test/test_cache_manager_for_iterator.py,sha256=OjJEEmvWtsGCPFXp2NQP2lpUGFXe9Zr2EpQSfRTDfRI,1147
|
68
68
|
kevin_toolbox/data_flow/core/reader/__init__.py,sha256=i2118MlsNSJHG5u6ZuPcN3NW2LZmYUtDO7dNEdnOncI,146
|
69
|
-
kevin_toolbox/data_flow/core/reader/file_iterative_reader.py,sha256=
|
70
|
-
kevin_toolbox/data_flow/core/reader/unified_reader.py,sha256=
|
69
|
+
kevin_toolbox/data_flow/core/reader/file_iterative_reader.py,sha256=l6UMYnvWwqQm3zEA2g5fDA1oJeKLlbRYnzrRJvuCxBg,10158
|
70
|
+
kevin_toolbox/data_flow/core/reader/unified_reader.py,sha256=l6JxPoDUOdx2ZIPX2WLXbGU3VZtTd1AeHn5q6L8GWAI,2453
|
71
71
|
kevin_toolbox/data_flow/core/reader/unified_reader_base.py,sha256=4gIADdV8UKpt2yD8dZjQsXFcF75nJ83ooIae3D7bw2s,11783
|
72
72
|
kevin_toolbox/data_flow/file/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
73
73
|
kevin_toolbox/data_flow/file/json_/__init__.py,sha256=VAt8COS2tO3PJRuhSc43i35fEOlArFM_YahdTmEBaHE,85
|
74
|
-
kevin_toolbox/data_flow/file/json_/read_json.py,sha256=
|
75
|
-
kevin_toolbox/data_flow/file/json_/write_json.py,sha256=
|
76
|
-
kevin_toolbox/data_flow/file/json_/converter/__init__.py,sha256=
|
74
|
+
kevin_toolbox/data_flow/file/json_/read_json.py,sha256=S-rlY-spIAJVyB-zPQOmKUDdtNAgedSmXHjkY_TNGUE,1808
|
75
|
+
kevin_toolbox/data_flow/file/json_/write_json.py,sha256=mWaxePr_QzfyeCb0hAy4xTKOGX7q0eFjep0jDqOqIgw,2379
|
76
|
+
kevin_toolbox/data_flow/file/json_/converter/__init__.py,sha256=oQMgAgzELLq_f4LIIfz5E6l_E7g4lFsXqfmnJ3tPZTY,401
|
77
77
|
kevin_toolbox/data_flow/file/json_/converter/convert_dict_key_to_number.py,sha256=SuSZj_HCqKZutHAJ5AttABnGBRZplPGQhMxJBt2Wlgc,559
|
78
78
|
kevin_toolbox/data_flow/file/json_/converter/convert_ndarray_to_list.py,sha256=GALpC1MFJ4aMzs0FZIfJScYznfCP-gmhPeM8sWXGSWg,391
|
79
79
|
kevin_toolbox/data_flow/file/json_/converter/escape_non_str_dict_key.py,sha256=83qwH_-v4A5UvSxdctE1TBdxw8PFewoctKEX5nECNG8,809
|
80
|
-
kevin_toolbox/data_flow/file/json_/converter/
|
80
|
+
kevin_toolbox/data_flow/file/json_/converter/escape_tuple_and_set.py,sha256=u4i8bG0Hgszh-3lEsmBmP4VWVOfJBfgXRyGxm1L3PvA,763
|
81
81
|
kevin_toolbox/data_flow/file/json_/converter/integrate.py,sha256=uEnRMqt4hTCVHL8p3tH7jir7mYSo3vGhZ4WS_Qi4Rms,377
|
82
82
|
kevin_toolbox/data_flow/file/json_/converter/unescape_non_str_dict_key.py,sha256=KDBjxJHn8q9dqM-kbtbUunjpc-6shZypYSyihVtkzgI,808
|
83
|
-
kevin_toolbox/data_flow/file/json_/converter/
|
83
|
+
kevin_toolbox/data_flow/file/json_/converter/unescape_tuple_and_set.py,sha256=3vCFr6CtNZxiVR1nRVDcuodIzHRfrmDsvBPCWtnWtBs,814
|
84
84
|
kevin_toolbox/data_flow/file/kevin_notation/__init__.py,sha256=g9UUF9nJrOMc0ndCwVROQLsux4Or2yVMJMdhK5P9nRc,259
|
85
85
|
kevin_toolbox/data_flow/file/kevin_notation/converter.py,sha256=5k_Yxw-fBKEkxFG0bnl1fRsz06MlUS-4f3gZ--bmDs8,3621
|
86
|
-
kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_reader.py,sha256=
|
86
|
+
kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_reader.py,sha256=iN6nV8mMbifTbECNmjc-G2pzpxivhks5kCXGVdvS9fQ,8297
|
87
87
|
kevin_toolbox/data_flow/file/kevin_notation/kevin_notation_writer.py,sha256=dyzkufi_SM-uU7cyI3yLFd8U4GnyRR5pyS88op6mhRY,16331
|
88
|
-
kevin_toolbox/data_flow/file/kevin_notation/read.py,sha256=
|
88
|
+
kevin_toolbox/data_flow/file/kevin_notation/read.py,sha256=w0RE0WwTmWycEozJVshAiE0gMBxproBRwBEMLS6tB6c,544
|
89
89
|
kevin_toolbox/data_flow/file/kevin_notation/write.py,sha256=gPabz_h2mtXqCTyBVzip_QSb6L4tsrNSqibFzuqsIv8,556
|
90
90
|
kevin_toolbox/data_flow/file/kevin_notation/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
91
|
-
kevin_toolbox/data_flow/file/kevin_notation/test/test_kevin_notation.py,sha256=
|
91
|
+
kevin_toolbox/data_flow/file/kevin_notation/test/test_kevin_notation.py,sha256=ab402r5LGyNz4XW2SnjvicNtQqBAAHZTaGfYMNdMExI,7345
|
92
92
|
kevin_toolbox/data_flow/file/kevin_notation/test/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
93
93
|
kevin_toolbox/data_flow/file/kevin_notation/test/test_data/data_0.py,sha256=CKRb86O3JV9lkGrMtyJzEH041o0xABfT32Zo4GQ5Qis,324
|
94
94
|
kevin_toolbox/data_flow/file/kevin_notation/test/test_data/data_1.py,sha256=Xs8oFJqwi0uPOJewulij7DY0iMEp6dWBMiiDIwPlm4s,176
|
@@ -96,7 +96,7 @@ kevin_toolbox/data_flow/file/kevin_notation/test/test_data/data_all.py,sha256=cv
|
|
96
96
|
kevin_toolbox/data_flow/file/markdown/__init__.py,sha256=iTZTBvcEUehBdcWxzFQEW4iEcXbAQkdkEmENiGtBjqs,125
|
97
97
|
kevin_toolbox/data_flow/file/markdown/generate_link.py,sha256=9okSyCFIDQW5T35a6-epVyoCkCL1vFH5215P5MRXfYk,304
|
98
98
|
kevin_toolbox/data_flow/file/markdown/generate_list.py,sha256=Gv5BcqWE4M4w8ADN8NX5LyD9DxILXTQtJvcazi_NuyE,1006
|
99
|
-
kevin_toolbox/data_flow/file/markdown/generate_table.py,sha256=
|
99
|
+
kevin_toolbox/data_flow/file/markdown/generate_table.py,sha256=Ct2gfnciBv0GGZHOKlIHyTlE7KqXsL0L5vBRCrQnOpI,7209
|
100
100
|
kevin_toolbox/developing/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
101
101
|
kevin_toolbox/developing/general_matrix_multiplication.py,sha256=Ie9c8mYBYR-Bg7CjU4L1dsOxXsxnx1jz-rA7_ez7vjg,2089
|
102
102
|
kevin_toolbox/developing/test.py,sha256=6Y23SY3FJVrvZmiiXKNPKv84lhVRW-XyjNeecj9lLYA,241
|
@@ -208,12 +208,12 @@ kevin_toolbox/math/transform/dct/dct_calculator.py,sha256=4goxXUMvYF3gkDH-lLFwX8
|
|
208
208
|
kevin_toolbox/math/transform/dct/generate_dct_trans_matrix.py,sha256=za6eaq0QoxZSiCj-hZ2dYjvpxMXcNABAHbVig811ER4,4305
|
209
209
|
kevin_toolbox/math/transform/scaling_and_shift/__init__.py,sha256=UXJcL7hyz1ag5rzz5eTvua36i76P4L2M94hhfV436pI,29
|
210
210
|
kevin_toolbox/math/transform/scaling_and_shift/scaling.py,sha256=HypsgC1KYsUmti6I0nEYzQpL1_343hXtfppDJ3ucje0,1280
|
211
|
-
kevin_toolbox/math/utils/__init__.py,sha256=
|
211
|
+
kevin_toolbox/math/utils/__init__.py,sha256=ceXYQaTpFeQD2QPutLz__bJlq3ECNbHUCnoLGUPHKok,289
|
212
212
|
kevin_toolbox/math/utils/convert_dtype.py,sha256=WW8KE5NlkjZ76BM48_cRClm41lZRybe6xnBBc4qEY70,1943
|
213
213
|
kevin_toolbox/math/utils/get_crop_by_box.py,sha256=oiM14a0jsyxOnVn5n0pU0chdNRc5VOw3_KbS7CArdfw,1620
|
214
214
|
kevin_toolbox/math/utils/get_function_table_for_array_and_tensor.py,sha256=hZrXb3427SMyMsUBcz5DWF2FhV-bSWzBqx5cvrvk_8w,1553
|
215
215
|
kevin_toolbox/math/utils/set_crop_by_box.py,sha256=NzW7M26Av097RchLUAhaO84ETLV121uxsNot_U6otLw,1775
|
216
|
-
kevin_toolbox/math/utils/
|
216
|
+
kevin_toolbox/math/utils/split_integer_most_evenly.py,sha256=6hTWKXYx3YlotNMaw8cmecWO0A4C_Ny2kxgN9asiN9A,345
|
217
217
|
kevin_toolbox/nested_dict_list/__init__.py,sha256=ALcn1tYdBdDWUHyIQj588UfHgrAwbUcZu_bN2v-cEAc,333
|
218
218
|
kevin_toolbox/nested_dict_list/copy_.py,sha256=MvzNRKm8htYpMe7Td1ao2-ZoaYVC_iNTG7O2SBVrJKE,6144
|
219
219
|
kevin_toolbox/nested_dict_list/count_leaf_node_nums.py,sha256=l67u47EvO1inoGinUqH6RZ7cHXwN0VcBQPUvSheqAvA,614
|
@@ -227,11 +227,12 @@ kevin_toolbox/nested_dict_list/name_handler/__init__.py,sha256=P_pWq78oN6NdvWg2h
|
|
227
227
|
kevin_toolbox/nested_dict_list/name_handler/build_name.py,sha256=VPWyjE8i8l-4Zm4tkD06Ie4J2NCsmI32ecOxZQqqmok,989
|
228
228
|
kevin_toolbox/nested_dict_list/name_handler/escape_node.py,sha256=niT9MxmsyrSZYhKXlWzdoKXVYhWRCR-kmQBkZopznpA,1163
|
229
229
|
kevin_toolbox/nested_dict_list/name_handler/parse_name.py,sha256=vUlAXPocpVSxtb3EnRi7U5K40Tz9plFG-_sbwLfYiy4,2280
|
230
|
-
kevin_toolbox/nested_dict_list/serializer/__init__.py,sha256=
|
230
|
+
kevin_toolbox/nested_dict_list/serializer/__init__.py,sha256=79dd9l-mNz0bycFKjNm7YsfWPR-JsVx9NoG_Ofqy-HQ,153
|
231
231
|
kevin_toolbox/nested_dict_list/serializer/enum_variable.py,sha256=RWPydtXI4adOJYGo_k5CWHSL0Odzj_bsahb24p1ranY,847
|
232
|
-
kevin_toolbox/nested_dict_list/serializer/read.py,sha256=
|
232
|
+
kevin_toolbox/nested_dict_list/serializer/read.py,sha256=yessvu7msmP2kV3ZhOTVmI2ENI-R1-TdhVgZdS8eWDk,2843
|
233
|
+
kevin_toolbox/nested_dict_list/serializer/saved_node_name_builder.py,sha256=qsD-rmDmVaKZP4owN3Wm3QY2Ksi71XlYETqw4VmIsSU,1011
|
233
234
|
kevin_toolbox/nested_dict_list/serializer/variable.py,sha256=ZywG6obipRBCGY1cY42gdvsuWk8GLZXr6eCYcW7ZJ9c,392
|
234
|
-
kevin_toolbox/nested_dict_list/serializer/write.py,sha256=
|
235
|
+
kevin_toolbox/nested_dict_list/serializer/write.py,sha256=kP_sM-NtI3vJT7KwBZsz_ReZprfVefzUFplW7Kh0zVQ,21024
|
235
236
|
kevin_toolbox/nested_dict_list/serializer/backends/__init__.py,sha256=8g7y-L3cmctxao616dVkGiot00FJzKNmNl_69V2bSmE,39
|
236
237
|
kevin_toolbox/nested_dict_list/serializer/backends/_json_.py,sha256=oJXIc28yjxsD9ZJuw120pVHTVsTzCdaXEhVUSQeydq4,2145
|
237
238
|
kevin_toolbox/nested_dict_list/serializer/backends/_ndl.py,sha256=QMF4DFAnt1sp35atds6t44nfCYuIOeGgW1-SPfJq6KM,1652
|
@@ -243,11 +244,12 @@ kevin_toolbox/nested_dict_list/serializer/backends/_skip_simple.py,sha256=dS9kKh
|
|
243
244
|
kevin_toolbox/nested_dict_list/serializer/backends/_torch_all.py,sha256=aw9M1Hep65lkvb8_QU3VkecE6q3l4UqXansh4lnMv7s,1282
|
244
245
|
kevin_toolbox/nested_dict_list/serializer/backends/_torch_tensor.py,sha256=Wiimzc0XGxFRYJiipzVnUd27scaJZZTOYp5OxYo3cKg,1353
|
245
246
|
kevin_toolbox/nested_dict_list/serializer/backends/backend_base.py,sha256=SZpLRhdSIykHZ_Ds3HX96lKLfXCyKzMQ_lx139XXBtc,1741
|
246
|
-
kevin_toolbox/nested_dict_list/value_parser/__init__.py,sha256=
|
247
|
+
kevin_toolbox/nested_dict_list/value_parser/__init__.py,sha256=MgbpkiXzVuA_i3VZ4VDNrQZfzpUZN3uaHrgOt_wq-4E,313
|
247
248
|
kevin_toolbox/nested_dict_list/value_parser/cal_relation_between_references.py,sha256=m3P7q5-pbbWqtjOjJUT-499q4mCyjtFEtFpGgovShSg,3119
|
248
249
|
kevin_toolbox/nested_dict_list/value_parser/eval_references.py,sha256=YQyOm3awKVRusXxSNObjJ2yPf0oE4gleobOn_RN_nzU,2301
|
249
250
|
kevin_toolbox/nested_dict_list/value_parser/parse_and_eval_references.py,sha256=RQEDFFNAhQQcX9H8curwja-pI2gKZlVx4M2qeneBOhA,2370
|
250
251
|
kevin_toolbox/nested_dict_list/value_parser/parse_references.py,sha256=G470xNzrRpYlS5To8R5yV0M6nX4iE5LLMp_eV49bh3Y,2116
|
252
|
+
kevin_toolbox/nested_dict_list/value_parser/replace_identical_with_reference.py,sha256=4nd5q3qTi4sTfOqHF0-HyLMDS9a5x8wgwETfpDI8jh8,5419
|
251
253
|
kevin_toolbox/patches/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
252
254
|
kevin_toolbox/patches/for_logging/__init__.py,sha256=xymF6mjwY4Cin7CoEwanFY5ZVk8oY0pDLqjZAGa7_Rg,39
|
253
255
|
kevin_toolbox/patches/for_logging/build_logger.py,sha256=0UoRMKaERd8wlHGTiNR3dbLQRAtXcb0QZuGkX2oFgGo,3071
|
@@ -263,7 +265,7 @@ kevin_toolbox/patches/for_numpy/linalg/entropy.py,sha256=PSdwkzySvWF4h4Xi27w2kvL
|
|
263
265
|
kevin_toolbox/patches/for_numpy/linalg/normalize.py,sha256=7qstt__rwUkk3jRJOQoneBp9YdfhYQtWfh6PZoWbvaA,625
|
264
266
|
kevin_toolbox/patches/for_numpy/linalg/softmax.py,sha256=M4a3jyKZBMFdiC_sPqO7AVts6AnEju8WbLc_GNSEtQ4,2095
|
265
267
|
kevin_toolbox/patches/for_numpy/random/__init__.py,sha256=f1nOm2jr-4x5ZW80S5VzvIAtag0aQTGiYVzxgGG1Oq8,149
|
266
|
-
kevin_toolbox/patches/for_numpy/random/get_rng.py,sha256=
|
268
|
+
kevin_toolbox/patches/for_numpy/random/get_rng.py,sha256=QblrMKg4OFVy-C4A6rQ-zq26uDKzhMifKTFUlyW3Ksw,1999
|
267
269
|
kevin_toolbox/patches/for_numpy/random/truncated_multivariate_normal.py,sha256=ZOaFZrzFI-ty7oRwUXxLx7pJMLTPPAAN28_AM6LeUDk,5859
|
268
270
|
kevin_toolbox/patches/for_numpy/random/truncated_normal.py,sha256=uej3SQnLu0HsBTD47Yrgft1NpnsoEIOm925H9ipS8UQ,3726
|
269
271
|
kevin_toolbox/patches/for_numpy/random/variable.py,sha256=Sam-QZgkx9_IvHzZhpUrXld0izP5MZfMBiM8qRWcB6M,231
|
@@ -302,7 +304,7 @@ kevin_toolbox/patches/for_torch/math/get_y_at_x.py,sha256=bfoVcasZ_tMdhR_1Me0Jli
|
|
302
304
|
kevin_toolbox/patches/for_torch/math/my_around.py,sha256=ptpU3ids50gwf663EpHbw7raj9tNrDGBFZ5t_uMNH14,1378
|
303
305
|
kevin_toolbox/patches/for_torch/nn/__init__.py,sha256=aJs3RMqRzQmd8KKDmQW9FxwCqS5yfPqEdg-m0PwlQro,39
|
304
306
|
kevin_toolbox/patches/for_torch/nn/lambda_layer.py,sha256=KUuLiX_Dr4bvRmpAaCW5QTDWDcnMPRnw0jg4NNXTFhM,223
|
305
|
-
kevin_toolbox_dev-1.3.
|
306
|
-
kevin_toolbox_dev-1.3.
|
307
|
-
kevin_toolbox_dev-1.3.
|
308
|
-
kevin_toolbox_dev-1.3.
|
307
|
+
kevin_toolbox_dev-1.3.4.dist-info/METADATA,sha256=NANoXo3yczTlDCHbDo38F_QLlPf0LBYWIwMS4fRHipY,2710
|
308
|
+
kevin_toolbox_dev-1.3.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
309
|
+
kevin_toolbox_dev-1.3.4.dist-info/top_level.txt,sha256=S5TeRGF-PwlhsaUEPTI-f2vWrpLmh3axpyI6v-Fi75o,14
|
310
|
+
kevin_toolbox_dev-1.3.4.dist-info/RECORD,,
|
@@ -1,20 +0,0 @@
|
|
1
|
-
def escape_tuple(x):
|
2
|
-
"""
|
3
|
-
将 tuple 进行转义
|
4
|
-
转义: x ==> f"<eval>{x}"
|
5
|
-
反转义: f"<eval>{x}" ==> x
|
6
|
-
|
7
|
-
为什么要进行转义?
|
8
|
-
由于 json 中会将 tuple 作为 list 进行保存,因此在保存过程中会丢失相应信息。
|
9
|
-
"""
|
10
|
-
if isinstance(x, tuple) or (isinstance(x, (str,)) and x.startswith("<eval>")):
|
11
|
-
return f'<eval>{x}'
|
12
|
-
else:
|
13
|
-
return x
|
14
|
-
|
15
|
-
|
16
|
-
if __name__ == '__main__':
|
17
|
-
print(escape_tuple((1, 2, "\'1\'")))
|
18
|
-
# <eval>(1, 2, "'1'")
|
19
|
-
print(escape_tuple("<eval>233"))
|
20
|
-
# <eval><eval>233
|
@@ -1,96 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: kevin-toolbox-dev
|
3
|
-
Version: 1.3.2
|
4
|
-
Summary: 一个常用的工具代码包集合
|
5
|
-
Home-page: https://github.com/cantbeblank96/kevin_toolbox
|
6
|
-
Download-URL: https://github.com/username/your-package/archive/refs/tags/v1.0.0.tar.gz
|
7
|
-
Author: kevin hsu
|
8
|
-
Author-email: xukaiming1996@163.com
|
9
|
-
License: MIT
|
10
|
-
Keywords: mathematics,pytorch,numpy,machine-learning,algorithm
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
12
|
-
Classifier: Programming Language :: Python
|
13
|
-
Classifier: Programming Language :: Python :: 3
|
14
|
-
Requires-Python: >=3.6
|
15
|
-
Description-Content-Type: text/markdown
|
16
|
-
Requires-Dist: torch (>=1.2.0)
|
17
|
-
Requires-Dist: numpy (>=1.19.0)
|
18
|
-
Provides-Extra: plot
|
19
|
-
Requires-Dist: matplotlib (>=3.0) ; extra == 'plot'
|
20
|
-
Provides-Extra: rest
|
21
|
-
Requires-Dist: pytest (>=6.2.5) ; extra == 'rest'
|
22
|
-
Requires-Dist: line-profiler (>=3.5) ; extra == 'rest'
|
23
|
-
|
24
|
-
# kevin_toolbox
|
25
|
-
|
26
|
-
一个通用的工具代码包集合
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
环境要求
|
31
|
-
|
32
|
-
```shell
|
33
|
-
numpy>=1.19
|
34
|
-
pytorch>=1.2
|
35
|
-
```
|
36
|
-
|
37
|
-
安装方法:
|
38
|
-
|
39
|
-
```shell
|
40
|
-
pip install kevin-toolbox --no-dependencies
|
41
|
-
```
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
[项目地址 Repo](https://github.com/cantbeblank96/kevin_toolbox)
|
46
|
-
|
47
|
-
[使用指南 User_Guide](./notes/User_Guide.md)
|
48
|
-
|
49
|
-
[免责声明 Disclaimer](./notes/Disclaimer.md)
|
50
|
-
|
51
|
-
[版本更新记录](./notes/Release_Record.md):
|
52
|
-
|
53
|
-
- v 1.3.2 (2024-03-05)【bug fix】【new feature】
|
54
|
-
- patches
|
55
|
-
- for_optuna.serialize
|
56
|
-
- 【bug fix】fix bug in for_study.dump(),使用 try except 来捕抓并跳过使用 getattr(study, k) 读取 study 中属性时产生的错误。(比如单变量优化时的best_trials参数)
|
57
|
-
- 【bug fix】fix bug in for_study.dump(),避免意外修改 study 中的属性。
|
58
|
-
- 添加了对应的测试用例。
|
59
|
-
- for_matplotlib
|
60
|
-
- 【new feature】add generate_color_list(),用于生成指定数量的颜色列表,支持对指定颜色的排除。
|
61
|
-
- for_numpy
|
62
|
-
- 【new feature】add linalg.entropy(),用于计算分布的熵。
|
63
|
-
- 【new feature】add random,添加了用于随机生成的模块,其中包含:
|
64
|
-
- get_rng(),获取默认随机生成器or根据指定的seed构建随机生成器。
|
65
|
-
- truncated_normal(),从截断的高斯分布中进行随机采样。
|
66
|
-
- truncated_multivariate_normal(),从截断的多维高斯分布中进行随机采样。
|
67
|
-
- 添加了测试用例。
|
68
|
-
- nested_dict_list
|
69
|
-
- 【bug fix】fix bug in get_nodes(),修复了遍历非叶节点时,当节点下的叶节点均不存在时会异常跳过该节点的问题。
|
70
|
-
- 添加了对应的测试用例。
|
71
|
-
- 【new feature】modify set_default(),修改后将默认返回对应name的值,而不是返回整体的var,从而与python dict的setdefault函数的行为对齐。特别地,也支持通过设置b_return_var参数来获取 var。
|
72
|
-
- 修改了对应的测试用例。
|
73
|
-
- computer_science.algorithm
|
74
|
-
- registration.Registry
|
75
|
-
- 【new feature】改进 self.collect_from_paths() 函数。
|
76
|
-
- 增加一个检查用于避免待搜索路径包含调用该函数的文件。如果包含,则报错,同时提示这样会导致 collect_from_paths() 函数被无限递归调用,从而引起死循环。并建议将该函数的调用位置放置在待搜索路径外,或者使用 ignore_s 将其进行屏蔽。
|
77
|
-
- 添加了测试用例。
|
78
|
-
- 【bug fix】fix bug in self.get(),之前 get() 函数中只从 `self._item_to_add`和 `self._path_to_collect` 中加载一次注册成员,但是加载的过程中,可能后面因为对 `self._path_to_collect` 的加载,又往 `self._item_to_add` 中添加了待处理内容,导致不能完全加载。该问题已修复。
|
79
|
-
- 添加了测试用例。
|
80
|
-
- 【new feature】add cache_manager,新增了 cache_manager 模块用于进行缓存管理。
|
81
|
-
- 其中主要包含三个部分:
|
82
|
-
- 缓存数据结构:cache_manager.cache 和 `cache_manager.variable.CACHE_BUILDER_REGISTRY`
|
83
|
-
- 基类:`Cache_Base`
|
84
|
-
- 基于内存的缓存结构:`Memo_Cache`,注册名 `":in_memory:Memo_Cache"` 等等。
|
85
|
-
- 缓存更新策略:cache_manager.strategy 和 `cache_manager.variable.CACHE_STRATEGY_REGISTRY`
|
86
|
-
- 基类:`Strategy_Base`
|
87
|
-
- 删除最后一次访问时间最久远的部分:`FIFO_Strategy`,注册名 `":by_initial_time:FIFO_Strategy"` 等等。
|
88
|
-
- 删除访问频率最低的部分:`LFU_Strategy`,注册名 `":by_counts:LFU_Strategy"` 等等。
|
89
|
-
- 删除最后一次访问时间最久远的部分:`LRU_Strategy`,注册名 `":by_last_time:LRU_Strategy"` 等等。
|
90
|
-
- 删除访问频率最低的部分:`LST_Strategy`,注册名 `":by_survival_time:LST_Strategy"` 等等。
|
91
|
-
- 缓存管理器:Cache_Manager(主要用这个)
|
92
|
-
- 添加了测试用例。
|
93
|
-
- data_flow.core.cache
|
94
|
-
- modify Cache_Manager_for_Iterator,使用新增的 cache_manager 模块替换 Cache_Manager_for_Iterator 中基于内存的缓存。相关参数有修改。
|
95
|
-
- 添加了测试用例。
|
96
|
-
|
File without changes
|
File without changes
|