xiaojing 0.0.1__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.
Potentially problematic release.
This version of xiaojing might be problematic. Click here for more details.
- ii_common/__init__.py +2 -0
- ii_common/ii_base_func/__init__.py +5 -0
- ii_common/ii_base_func/ii_ant.py +6 -0
- ii_common/ii_base_func/ii_class.py +30 -0
- ii_common/ii_base_func/ii_file.py +35 -0
- ii_common/ii_base_func/ii_model.py +57 -0
- ii_common/ii_base_func/ii_path.py +41 -0
- ii_common/ii_base_func/ii_str.py +6 -0
- ii_common/ii_base_func/ii_time.py +75 -0
- ii_common/ii_call_func/__init__.py +3 -0
- ii_common/ii_call_func/ii_ant.py +6 -0
- ii_common/ii_call_func/ii_judge.py +21 -0
- ii_common/ii_call_func/ii_sqlite.py +145 -0
- ii_common/ii_call_func/ii_tools.py +119 -0
- xiaojing-0.0.1.dist-info/METADATA +23 -0
- xiaojing-0.0.1.dist-info/RECORD +18 -0
- xiaojing-0.0.1.dist-info/WHEEL +5 -0
- xiaojing-0.0.1.dist-info/top_level.txt +1 -0
ii_common/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["Singleton", "Shape"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Singleton(type):
|
|
7
|
+
"""类的单例模式"""
|
|
8
|
+
_instances = {}
|
|
9
|
+
|
|
10
|
+
def __call__(cls, *args, **kwargs):
|
|
11
|
+
"""
|
|
12
|
+
:param cls: 类
|
|
13
|
+
:param args: 位置参数
|
|
14
|
+
:param kwargs: 关键字参数
|
|
15
|
+
"""
|
|
16
|
+
if cls not in cls._instances:
|
|
17
|
+
cls._instances[cls] = super().__call__(*args, **kwargs)
|
|
18
|
+
return cls._instances[cls]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Shape(abc.ABC):
|
|
22
|
+
"""抽象基类"""
|
|
23
|
+
|
|
24
|
+
@abc.abstractmethod
|
|
25
|
+
def area(self):
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abc.abstractmethod
|
|
29
|
+
def perimeter(self):
|
|
30
|
+
pass
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["FileInfo", "get_file_size_str"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FileInfo:
|
|
7
|
+
def __init__(self, m_path):
|
|
8
|
+
"""
|
|
9
|
+
获取文件信息
|
|
10
|
+
:param m_path: 文件路径
|
|
11
|
+
"""
|
|
12
|
+
self.size = get_file_size_str(m_path)
|
|
13
|
+
self.ctime = datetime.datetime.fromtimestamp(os.path.getctime(m_path)).strftime('%Y-%m-%d %H:%M:%S')
|
|
14
|
+
self.mtime = datetime.datetime.fromtimestamp(os.path.getmtime(m_path)).strftime('%Y-%m-%d %H:%M:%S')
|
|
15
|
+
|
|
16
|
+
def __str__(self):
|
|
17
|
+
"""
|
|
18
|
+
返回文件信息
|
|
19
|
+
"""
|
|
20
|
+
return json.dumps({"size": self.size, "ctime": self.ctime, "mtime": self.mtime}, ensure_ascii=False)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_file_size_str(m_path):
|
|
24
|
+
"""
|
|
25
|
+
获取文件大小字符串
|
|
26
|
+
:param m_path: 文件路径
|
|
27
|
+
:return: 文件大小字符串
|
|
28
|
+
"""
|
|
29
|
+
ff_file_size = os.path.getsize(m_path)
|
|
30
|
+
for unit in ['B', 'KB', 'MB', 'GB']:
|
|
31
|
+
if abs(ff_file_size) < 1024.0:
|
|
32
|
+
return "{:3.1f} {}".format(ff_file_size, unit)
|
|
33
|
+
ff_file_size /= 1024.0
|
|
34
|
+
# 如果文件大小大于最大单位,则返回 GB 单位的文件大小字符串
|
|
35
|
+
return "{:.1f}GB".format(ff_file_size)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["func_mapping"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FuncMapping:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.__model_mapping = {}
|
|
9
|
+
|
|
10
|
+
def add_by_path(self, m_path, m_func, m_name):
|
|
11
|
+
"""
|
|
12
|
+
添加模型
|
|
13
|
+
:param m_path: 模块路径
|
|
14
|
+
:param m_func: 模块中函数名
|
|
15
|
+
:param m_name: 模块中函数名
|
|
16
|
+
"""
|
|
17
|
+
if not m_path.endswith(".py"):
|
|
18
|
+
raise Exception("Module path must be a .py file")
|
|
19
|
+
ff_path, ff_name = os.path.split(m_path)
|
|
20
|
+
sys.path.append(ff_path)
|
|
21
|
+
ff_func = getattr(importlib.import_module(os.path.splitext(ff_name)[0]), m_func)
|
|
22
|
+
if not isinstance(ff_func, FunctionType):
|
|
23
|
+
raise Exception("Model function must be a function")
|
|
24
|
+
self.__model_mapping[m_name] = ff_func
|
|
25
|
+
|
|
26
|
+
def add_by_func(self, m_name, m_func):
|
|
27
|
+
"""
|
|
28
|
+
添加模型
|
|
29
|
+
:param m_name: 模型名称
|
|
30
|
+
:param m_func: 模型函数
|
|
31
|
+
"""
|
|
32
|
+
if not isinstance(m_func, FunctionType):
|
|
33
|
+
raise Exception("Model function must be a function")
|
|
34
|
+
self.__model_mapping[m_name] = m_func
|
|
35
|
+
|
|
36
|
+
def get_func(self, m_name):
|
|
37
|
+
"""
|
|
38
|
+
获取模型
|
|
39
|
+
:param m_name: 模型名称
|
|
40
|
+
"""
|
|
41
|
+
return self.__model_mapping.get(m_name)
|
|
42
|
+
|
|
43
|
+
def remove_func(self, m_name):
|
|
44
|
+
"""
|
|
45
|
+
移除模型
|
|
46
|
+
:param m_name: 模型名称
|
|
47
|
+
"""
|
|
48
|
+
self.__model_mapping.pop(m_name)
|
|
49
|
+
|
|
50
|
+
def clear_all(self):
|
|
51
|
+
"""
|
|
52
|
+
清空模型
|
|
53
|
+
"""
|
|
54
|
+
self.__model_mapping.clear()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
func_mapping = FuncMapping()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["path_to_abs", "path_to_rel", "PathSplit"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def path_to_abs(m_path):
|
|
7
|
+
"""
|
|
8
|
+
将相对路径转换为绝对路径
|
|
9
|
+
:param m_path: 相对路径
|
|
10
|
+
:return: 绝对路径
|
|
11
|
+
"""
|
|
12
|
+
if not os.path.isabs(m_path):
|
|
13
|
+
m_path = os.path.abspath(os.path.join(os.getcwd(), m_path))
|
|
14
|
+
return m_path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def path_to_rel(m_path, m_origin=os.getcwd()):
|
|
18
|
+
"""
|
|
19
|
+
将绝对路径转换为相对路径
|
|
20
|
+
:param m_path: 绝对路径
|
|
21
|
+
:param m_origin: 相对路径的起始目录
|
|
22
|
+
:return: 相对路径
|
|
23
|
+
"""
|
|
24
|
+
if os.path.isabs(m_path):
|
|
25
|
+
m_path = os.path.relpath(m_path, start=m_origin)
|
|
26
|
+
return m_path
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class PathSplit:
|
|
30
|
+
"""
|
|
31
|
+
路径分割
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, m_path):
|
|
35
|
+
"""
|
|
36
|
+
初始化
|
|
37
|
+
:param m_path: 路径
|
|
38
|
+
"""
|
|
39
|
+
self.path = os.path.split(m_path)[0]
|
|
40
|
+
self.name, self.suffix = os.path.splitext(os.path.basename(m_path))
|
|
41
|
+
self.suffix = self.suffix.strip(".")
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["time_now", "time_format"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def time_now(n_kind: str = None, n_out_format: str = None) -> str:
|
|
7
|
+
"""
|
|
8
|
+
获取当前时间
|
|
9
|
+
:param n_kind: 格式化类型(n,ny,nyr,s,sf,sfm,name)
|
|
10
|
+
:param n_out_format: 输出时间的格式化
|
|
11
|
+
"""
|
|
12
|
+
return time_format(
|
|
13
|
+
m_time=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))),
|
|
14
|
+
n_kind=n_kind,
|
|
15
|
+
n_out_format=n_out_format,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def time_format(m_time, n_kind: str = None, n_in_format: str = None, n_out_format: str = None) -> str:
|
|
20
|
+
"""
|
|
21
|
+
格式化时间
|
|
22
|
+
:param m_time: 待格式化的时间
|
|
23
|
+
:param n_kind: 格式化类型(n,ny,nyr,s,sf,sfm,name)
|
|
24
|
+
:param n_in_format: 输入时间的格式化
|
|
25
|
+
:param n_out_format: 输出时间的格式化
|
|
26
|
+
"""
|
|
27
|
+
time_pattern = r"(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d+) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}:\d{2}:\d{2}) "
|
|
28
|
+
if n_out_format is None:
|
|
29
|
+
if n_kind == "n":
|
|
30
|
+
n_out_format = "%Y"
|
|
31
|
+
elif n_kind == "ny":
|
|
32
|
+
n_out_format = "%Y%m"
|
|
33
|
+
elif n_kind == "nyr":
|
|
34
|
+
n_out_format = "%Y%m%d"
|
|
35
|
+
elif n_kind == "s":
|
|
36
|
+
n_out_format = "%Y%m%d%H"
|
|
37
|
+
elif n_kind == "sf":
|
|
38
|
+
n_out_format = "%Y%m%d%H%M"
|
|
39
|
+
elif n_kind == "sfm":
|
|
40
|
+
n_out_format = "%Y%m%d%H%M%S"
|
|
41
|
+
elif n_kind == "name":
|
|
42
|
+
n_out_format = "%Y%m%d-%H%M%S-%f"
|
|
43
|
+
elif n_kind is None:
|
|
44
|
+
n_out_format = "%Y-%m-%d %H:%M:%S.%f"
|
|
45
|
+
else:
|
|
46
|
+
n_out_format = n_kind
|
|
47
|
+
if n_in_format is not None:
|
|
48
|
+
return datetime.datetime.strptime(m_time, n_in_format).strftime(n_out_format)
|
|
49
|
+
elif type(m_time) is datetime.datetime:
|
|
50
|
+
return m_time.strftime(n_out_format)
|
|
51
|
+
elif type(m_time) is time.struct_time:
|
|
52
|
+
return time.strftime(n_out_format, m_time)
|
|
53
|
+
elif type(m_time) is str and re.match(time_pattern, m_time):
|
|
54
|
+
original_dt = datetime.datetime.strptime(m_time, "%a, %d %b %Y %H:%M:%S %Z") # 解析原始时间字符串
|
|
55
|
+
timestamp = time.mktime(original_dt.timetuple()) # 计算原始时间的UTC时间戳
|
|
56
|
+
beijing_timestamp = timestamp + 8 * 3600 # 计算北京时间的时间戳
|
|
57
|
+
beijing_dt = datetime.datetime.fromtimestamp(beijing_timestamp)
|
|
58
|
+
return beijing_dt.strftime(n_out_format) # 按指定格式输出北京时间字符串
|
|
59
|
+
elif type(m_time) is float:
|
|
60
|
+
return datetime.datetime.fromtimestamp(m_time).strftime(n_out_format)
|
|
61
|
+
elif type(m_time) is str and re.match("^[0-9]{4}$", m_time):
|
|
62
|
+
return datetime.datetime.strptime(m_time, "%Y").strftime(n_out_format)
|
|
63
|
+
elif type(m_time) is str and re.match("^[0-9]{8}$", m_time):
|
|
64
|
+
return datetime.datetime.strptime(m_time, "%Y%m%d").strftime(n_out_format)
|
|
65
|
+
elif type(m_time) is str and re.match("^[0-9]{4}-[0-9]{2}-[0-9]{2}$", m_time):
|
|
66
|
+
return datetime.datetime.strptime(m_time, "%Y-%m-%d").strftime(n_out_format)
|
|
67
|
+
elif type(m_time) is str and re.match(
|
|
68
|
+
"^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$", m_time):
|
|
69
|
+
return datetime.datetime.strptime(m_time[:19], "%Y-%m-%d %H:%M:%S").strftime(n_out_format)
|
|
70
|
+
elif type(m_time) is str and re.match("^[0-9]{8}-[0-9]{6}-[0-9]{6}$", m_time):
|
|
71
|
+
return datetime.datetime.strptime(m_time[:19], "%Y%m%d-%H%M%S-%f").strftime(n_out_format)
|
|
72
|
+
elif type(m_time) is str and re.match("^[0-9]{8}-[0-9]{6}$", m_time):
|
|
73
|
+
return datetime.datetime.strptime(m_time[:19], "%Y%m%d-%H%M%S").strftime(n_out_format)
|
|
74
|
+
elif type(m_time) is str and re.match("^[0-9]{14}$", m_time):
|
|
75
|
+
return datetime.datetime.strptime(m_time[:19], "%Y%m%d%H%M%S").strftime(n_out_format)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["not_none", "is_none"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def not_none(m_data):
|
|
7
|
+
"""
|
|
8
|
+
判断是否为空
|
|
9
|
+
:param m_data: 数据
|
|
10
|
+
"""
|
|
11
|
+
return not is_none(m_data)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def is_none(m_data):
|
|
15
|
+
"""
|
|
16
|
+
判断是否为空
|
|
17
|
+
:param m_data: 数据
|
|
18
|
+
"""
|
|
19
|
+
if isinstance(m_data, (float, int, complex)):
|
|
20
|
+
return numpy.isnan(m_data)
|
|
21
|
+
return not m_data
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
__all__ = ["SqliteDB"]
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SqliteDB:
|
|
7
|
+
"""
|
|
8
|
+
sqlite数据库操作类
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, m_path):
|
|
12
|
+
"""
|
|
13
|
+
初始化
|
|
14
|
+
:param m_path: 数据库文件路径
|
|
15
|
+
"""
|
|
16
|
+
self.db = m_path
|
|
17
|
+
self.cn = sqlite3.connect(database=self.db)
|
|
18
|
+
self.cs = self.cn.cursor()
|
|
19
|
+
self.tb = self.crud(self.cn, "SELECT name FROM `sqlite_master` WHERE type='table'")
|
|
20
|
+
self.fi = dict(json.loads(FileInfo(self.db).__str__()))
|
|
21
|
+
|
|
22
|
+
def __str__(self):
|
|
23
|
+
"""
|
|
24
|
+
返回字符串, 方便打印
|
|
25
|
+
"""
|
|
26
|
+
return json.dumps({"db": self.db, "fi": self.fi, "tb": self.tb}, ensure_ascii=False, default=str)
|
|
27
|
+
|
|
28
|
+
def cursor(self):
|
|
29
|
+
"""
|
|
30
|
+
获取游标, 开始事务
|
|
31
|
+
"""
|
|
32
|
+
ff_cursor = self.cn.cursor()
|
|
33
|
+
ff_cursor.execute('BEGIN')
|
|
34
|
+
return ff_cursor
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def commit(m_curs):
|
|
38
|
+
"""
|
|
39
|
+
提交事务
|
|
40
|
+
"""
|
|
41
|
+
m_curs.execute('COMMIT')
|
|
42
|
+
|
|
43
|
+
def vacuum(self):
|
|
44
|
+
"""
|
|
45
|
+
优化数据库, 释放空间
|
|
46
|
+
"""
|
|
47
|
+
self.cs.execute('VACUUM;')
|
|
48
|
+
self.cn.commit()
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def crud(m_curs, m_sql: str, n_value=None):
|
|
52
|
+
"""
|
|
53
|
+
执行sql语句方法
|
|
54
|
+
:param m_curs: 游标
|
|
55
|
+
:param m_sql: 查询语句
|
|
56
|
+
:param n_value: 查询参数
|
|
57
|
+
"""
|
|
58
|
+
if n_value is None: # X执行sql语句方法
|
|
59
|
+
ff_queried = m_curs.execute(m_sql)
|
|
60
|
+
elif type(n_value) is list:
|
|
61
|
+
ff_queried = m_curs.executemany(m_sql, n_value)
|
|
62
|
+
else:
|
|
63
|
+
ff_queried = m_curs.execute(m_sql, n_value)
|
|
64
|
+
ff_rows = ff_queried.fetchall() # X获取表名
|
|
65
|
+
if ff_rows:
|
|
66
|
+
columns = [description[0] for description in ff_queried.description]
|
|
67
|
+
ff_mid_rows = []
|
|
68
|
+
for row in ff_rows:
|
|
69
|
+
ff_mid_rows.append(dict(zip(columns, row)))
|
|
70
|
+
ff_rows = ff_mid_rows
|
|
71
|
+
return ff_rows
|
|
72
|
+
|
|
73
|
+
def create(self, m_dict, m_tb, n_primary: str = None, n_unique: list = None):
|
|
74
|
+
"""
|
|
75
|
+
创建表
|
|
76
|
+
:param m_dict: 字段名和类型
|
|
77
|
+
:param m_tb: 表名
|
|
78
|
+
:param n_primary: 主键
|
|
79
|
+
:param n_unique: 唯一键
|
|
80
|
+
"""
|
|
81
|
+
columns = "`" + "`,`".join(m_dict.keys()) + "`" # 获取所有的键(字段名),并用逗号分隔
|
|
82
|
+
if n_primary is None:
|
|
83
|
+
n_primary = list(m_dict.keys())[0]
|
|
84
|
+
create_sql = f"CREATE TABLE IF NOT EXISTS {m_tb} ({columns})".replace(
|
|
85
|
+
f"`{n_primary}`,", f"`{n_primary}` PRIMARY KEY,"
|
|
86
|
+
)
|
|
87
|
+
if n_unique is not None:
|
|
88
|
+
create_sql = create_sql[:-1] + f',UNIQUE({",".join(n_unique)}))'
|
|
89
|
+
self.crud(m_curs=self.cs, m_sql=create_sql)
|
|
90
|
+
|
|
91
|
+
def insert_one_json(self, m_curs, m_tb: str, m_dict: dict):
|
|
92
|
+
"""
|
|
93
|
+
插入一条数据
|
|
94
|
+
:param m_curs: 游标
|
|
95
|
+
:param m_tb: 表名
|
|
96
|
+
:param m_dict: 数据
|
|
97
|
+
"""
|
|
98
|
+
ff_columns_str = ", ".join(m_dict.keys())
|
|
99
|
+
ff_values_list = [m_dict.get(key, None) for key in m_dict]
|
|
100
|
+
ff_placeholder_str = ", ".join("?" * len(ff_values_list))
|
|
101
|
+
ff_insert_sql = f"INSERT OR IGNORE INTO {m_tb} ({ff_columns_str}) VALUES ({ff_placeholder_str})"
|
|
102
|
+
self.crud(m_curs=m_curs, m_sql=ff_insert_sql, n_value=tuple(ff_values_list))
|
|
103
|
+
|
|
104
|
+
def insert_many_json(self, m_curs, m_tb: str, m_list: list):
|
|
105
|
+
"""
|
|
106
|
+
插入多条数据
|
|
107
|
+
:param m_curs: 游标
|
|
108
|
+
:param m_tb: 表名
|
|
109
|
+
:param m_list: 数据
|
|
110
|
+
"""
|
|
111
|
+
ff_columns_set = set()
|
|
112
|
+
for ff_item in m_list:
|
|
113
|
+
ff_columns_set.update(ff_item.keys())
|
|
114
|
+
ff_columns_list = sorted(list(ff_columns_set))
|
|
115
|
+
ff_columns_str = ", ".join(ff_columns_list)
|
|
116
|
+
ff_placeholder_str = ", ".join("?" for i in range(len(ff_columns_list)))
|
|
117
|
+
ff_insert_sql = f"INSERT OR IGNORE INTO {m_tb} ({ff_columns_str}) VALUES ({ff_placeholder_str})"
|
|
118
|
+
ff_values_list = []
|
|
119
|
+
for ff_item in m_list:
|
|
120
|
+
ff_row_data = [ff_item.get(column, None) for column in ff_columns_list]
|
|
121
|
+
ff_row_data = [(json.dumps(i, ensure_ascii=False) if type(i) in [dict, list] else i) for i in ff_row_data]
|
|
122
|
+
ff_values_list.append(tuple(ff_row_data))
|
|
123
|
+
self.crud(m_curs=m_curs, m_sql=ff_insert_sql, n_value=ff_values_list)
|
|
124
|
+
|
|
125
|
+
def query_many_json(self, m_curs, m_tb, n_keys: list = None, n_mapping=None, n_skip=0, n_limit='-1'):
|
|
126
|
+
"""
|
|
127
|
+
查询多条数据
|
|
128
|
+
:param m_curs: 游标
|
|
129
|
+
:param m_tb: 表名
|
|
130
|
+
:param n_keys: 查询的字段名
|
|
131
|
+
:param n_mapping: 查询条件
|
|
132
|
+
:param n_skip: 跳过多少条
|
|
133
|
+
:param n_limit: 查询多少条
|
|
134
|
+
"""
|
|
135
|
+
if n_keys is None:
|
|
136
|
+
n_keys = "*"
|
|
137
|
+
else:
|
|
138
|
+
n_keys = ",".join(n_keys)
|
|
139
|
+
if n_mapping is None:
|
|
140
|
+
n_mapping = ""
|
|
141
|
+
else:
|
|
142
|
+
n_mapping = "where " + " and ".join([f"{k}='{v}'" for k, v in n_mapping.items()])
|
|
143
|
+
ff_sql_query = f"select {n_keys} from {m_tb} {n_mapping} limit {n_skip},{n_limit}"
|
|
144
|
+
self.crud(m_curs=m_curs, m_sql=ff_sql_query)
|
|
145
|
+
pass
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from .ii_ant import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Tqdm:
|
|
5
|
+
"""
|
|
6
|
+
进度条
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, m_iterable, n_desc="Processing", n_interval=0.23):
|
|
10
|
+
"""
|
|
11
|
+
:param m_iterable: 可迭代对象
|
|
12
|
+
:param n_desc: 描述
|
|
13
|
+
:param n_interval: 更新间隔
|
|
14
|
+
"""
|
|
15
|
+
# 将传入的可迭代对象赋值给实例变量ff_iterable
|
|
16
|
+
self.ff_iterable = m_iterable
|
|
17
|
+
# 将可迭代对象转换为列表并赋值给实例变量ff_keys
|
|
18
|
+
self.ff_keys = list(m_iterable)
|
|
19
|
+
# 计算ff_keys的长度并赋值给实例变量ff_total
|
|
20
|
+
self.ff_total = len(self.ff_keys)
|
|
21
|
+
# 将传入的描述赋值给实例变量ff_desc
|
|
22
|
+
self.ff_desc = n_desc
|
|
23
|
+
# 初始化当前进度为0
|
|
24
|
+
self.ff_current = 0
|
|
25
|
+
# 初始化进度条宽度为40
|
|
26
|
+
self.ff_width = 40
|
|
27
|
+
# 创建一个线程锁并赋值给实例变量ff_lock
|
|
28
|
+
self.ff_lock = threading.Lock()
|
|
29
|
+
# 初始化总时间为0
|
|
30
|
+
self.ff_total_time = 0
|
|
31
|
+
# 记录开始时间
|
|
32
|
+
self.ff_start_time = time.monotonic()
|
|
33
|
+
# 初始化已用时间为0
|
|
34
|
+
self.ff_elapsed_time = 0
|
|
35
|
+
# 初始化平均时间为0
|
|
36
|
+
self.ff_avg_time = 0
|
|
37
|
+
# 将传入的更新间隔赋值给实例变量ff_update_interval
|
|
38
|
+
self.ff_update_interval = n_interval
|
|
39
|
+
# 创建一个线程并指定线程执行的目标方法为progress_bar
|
|
40
|
+
self.ff_progress_thread = threading.Thread(target=self.progress_bar, daemon=True)
|
|
41
|
+
# 启动进度条线程
|
|
42
|
+
self.ff_progress_thread.start()
|
|
43
|
+
|
|
44
|
+
def progress_bar(self):
|
|
45
|
+
"""
|
|
46
|
+
子线程更新进度条
|
|
47
|
+
"""
|
|
48
|
+
# 记录上次更新时间
|
|
49
|
+
last_update_time = time.monotonic()
|
|
50
|
+
while True:
|
|
51
|
+
with self.ff_lock:
|
|
52
|
+
# 计算进度
|
|
53
|
+
progress = self.ff_current / self.ff_total if self.ff_total > 0 else 0
|
|
54
|
+
# 转换为百分比
|
|
55
|
+
percentage = int(progress * 100)
|
|
56
|
+
# 生成进度条字符串
|
|
57
|
+
bar = "|" + "\033[32m" + "#" * int(progress * self.ff_width) + "-" * (
|
|
58
|
+
self.ff_width - int(progress * self.ff_width)) + "\033[0m" + "|"
|
|
59
|
+
# 生成消息字符串
|
|
60
|
+
msg = "\033[34m" + f"{self.ff_desc}: {self.ff_current}/{self.ff_total} ({percentage}%)" + "\033[0m"
|
|
61
|
+
# 获取当前时间
|
|
62
|
+
current_time = time.monotonic()
|
|
63
|
+
# 计算已用时间
|
|
64
|
+
self.ff_elapsed_time += current_time - last_update_time
|
|
65
|
+
# 更新上次更新时间
|
|
66
|
+
last_update_time = current_time
|
|
67
|
+
# 如果当前进度大于0,则计算平均时间
|
|
68
|
+
if self.ff_current > 1:
|
|
69
|
+
self.ff_avg_time = self.ff_total_time / (self.ff_current - 1)
|
|
70
|
+
# 格式化平均时间字符串
|
|
71
|
+
time_per_item = f"{self.ff_avg_time:.2f}s/item"
|
|
72
|
+
# 生成已用时间消息字符串
|
|
73
|
+
elapsed_msg = "\033[35m" + f"Elapsed: {self.ff_elapsed_time:.2f}s ({time_per_item})" + "\033[0m"
|
|
74
|
+
# 计算剩余时间
|
|
75
|
+
remaining_time = (self.ff_total - self.ff_current) * self.ff_avg_time if self.ff_current > 0 else 0
|
|
76
|
+
# 将剩余时间转换为日期时间格式
|
|
77
|
+
remaining_datetime = datetime.datetime.fromtimestamp(time.time() + remaining_time)
|
|
78
|
+
# 生成预计剩余时间消息字符串
|
|
79
|
+
remaining_msg = "\033[36m" + f"ETA: {remaining_datetime.strftime('%F %T')}" + "\033[0m"
|
|
80
|
+
# 输出进度条和相关信息到控制台
|
|
81
|
+
sys.stdout.write(f"\r{msg} {bar} {elapsed_msg} {remaining_msg}")
|
|
82
|
+
sys.stdout.flush()
|
|
83
|
+
# 如果当前进度达到总进度,则跳出循环
|
|
84
|
+
if self.ff_current >= self.ff_total:
|
|
85
|
+
break
|
|
86
|
+
# 休眠一段时间
|
|
87
|
+
time.sleep(self.ff_update_interval)
|
|
88
|
+
# 输出换行符
|
|
89
|
+
sys.stdout.write("\n")
|
|
90
|
+
|
|
91
|
+
def __iter__(self):
|
|
92
|
+
return self
|
|
93
|
+
|
|
94
|
+
def __next__(self):
|
|
95
|
+
"""
|
|
96
|
+
:return: 返回下一个元素
|
|
97
|
+
"""
|
|
98
|
+
with self.ff_lock:
|
|
99
|
+
# 如果当前进度小于总进度
|
|
100
|
+
if self.ff_current < self.ff_total:
|
|
101
|
+
# 记录开始时间
|
|
102
|
+
start_time = self.ff_start_time
|
|
103
|
+
# 当前进度加1
|
|
104
|
+
self.ff_current += 1
|
|
105
|
+
# 获取当前进度的元素
|
|
106
|
+
result = self.ff_keys[self.ff_current - 1]
|
|
107
|
+
# 记录结束时间
|
|
108
|
+
end_time = time.monotonic()
|
|
109
|
+
# 计算当前元素的处理时间
|
|
110
|
+
item_time = end_time - start_time
|
|
111
|
+
# 累加总处理时间
|
|
112
|
+
self.ff_total_time += item_time
|
|
113
|
+
# 更新开始时间为当前时间
|
|
114
|
+
self.ff_start_time = time.monotonic()
|
|
115
|
+
# 返回当前元素
|
|
116
|
+
return result
|
|
117
|
+
else:
|
|
118
|
+
# 如果当前进度已经达到总进度,则抛出停止迭代的异常
|
|
119
|
+
raise StopIteration
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: xiaojing
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: 皛鲸的工具箱
|
|
5
|
+
Home-page: https://xiaojing.cc/python
|
|
6
|
+
Author: liuxiaojing
|
|
7
|
+
Author-email: lqxnjk@qq.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
Requires-Dist: pandas ==1.3.5
|
|
14
|
+
Requires-Dist: xlrd ==1.2.0
|
|
15
|
+
Requires-Dist: pymysql
|
|
16
|
+
Requires-Dist: requests
|
|
17
|
+
Requires-Dist: openpyxl
|
|
18
|
+
Requires-Dist: sqlalchemy
|
|
19
|
+
Requires-Dist: pymongo
|
|
20
|
+
|
|
21
|
+
python .\setup.py sdist
|
|
22
|
+
|
|
23
|
+
pip install .\dist\xiaojingcc-2.0.0.tar.gz
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
ii_common/__init__.py,sha256=S_-hR8HfeyuTQ280dc6SQT5kpUjOxlO3PY5Vk0csfFo,58
|
|
2
|
+
ii_common/ii_base_func/__init__.py,sha256=TdrAg1TiolAQEybmS7LkgEfeg3SnsX3CNjLxHPXoz3Y,122
|
|
3
|
+
ii_common/ii_base_func/ii_ant.py,sha256=ilEj166ABMkC8WS6seTNGUToBUa0MSDlCIbi6w6lv5Q,136
|
|
4
|
+
ii_common/ii_base_func/ii_class.py,sha256=cOToqN8NdeJfaDh7lcjSXKLvT9vz1HIvarwIgdvvCIs,640
|
|
5
|
+
ii_common/ii_base_func/ii_file.py,sha256=GANRLa-erfmKarUdq0nPQPaGBmshJdBaPS-vzWGAYbU,1180
|
|
6
|
+
ii_common/ii_base_func/ii_model.py,sha256=xakevxTO6WKxvW-6UcAiWM6SRISyVclzioG1VlLDTOU,1624
|
|
7
|
+
ii_common/ii_base_func/ii_path.py,sha256=-fQRwzK5-KPAC3fOvWcAfJhDz3_-Cxz3pQZqBoAm4xU,1021
|
|
8
|
+
ii_common/ii_base_func/ii_str.py,sha256=17jfxHjTI62_BBQAYaauX0JQr1PuOuGeXazEsPY2gcI,218
|
|
9
|
+
ii_common/ii_base_func/ii_time.py,sha256=-CuMUvjghXLNrdb60HxJijuVE_7bMz_CWp3hyzGrALs,3760
|
|
10
|
+
ii_common/ii_call_func/__init__.py,sha256=Ma74cgDz4ROU9LZUqvCb0vdEuwMPuMUqbde5zcwiHZA,76
|
|
11
|
+
ii_common/ii_call_func/ii_ant.py,sha256=RkiS_QxIbZHUFmVLltbqa5C8j_UcKnTzkKETTT-mVmk,124
|
|
12
|
+
ii_common/ii_call_func/ii_judge.py,sha256=AUSlvD-0xvtBx_j-4zcnweHdHaIAxT7wyxZ2K1nb0Hs,393
|
|
13
|
+
ii_common/ii_call_func/ii_sqlite.py,sha256=ftTtududOZYUH4ieR3Ucx4d_CihxPxyiSh0Bx0JZcMg,5296
|
|
14
|
+
ii_common/ii_call_func/ii_tools.py,sha256=QCsloau-HfRybvD93IzgTGFySI-20BT44vJ5G-Nd16A,5284
|
|
15
|
+
xiaojing-0.0.1.dist-info/METADATA,sha256=5kloYmty4gEaD9pC9tp910esr_z8oIHt87DaFxUmJPQ,610
|
|
16
|
+
xiaojing-0.0.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
17
|
+
xiaojing-0.0.1.dist-info/top_level.txt,sha256=DcvdeZvrHE1H3OKCGxfCbhmWKiCmsXi9nNUc9tJ2ImQ,10
|
|
18
|
+
xiaojing-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ii_common
|