database-smartools 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.
- database_smartools/__init__.py +18 -0
- database_smartools/api/__init__.py +18 -0
- database_smartools/api/etl.py +160 -0
- database_smartools/database/__init__.py +18 -0
- database_smartools/database/dameng_extend.py +65 -0
- database_smartools/database/db_handler.py +676 -0
- database_smartools/database/mysql_extend.py +396 -0
- database_smartools/database/oceanbase_extend.py +55 -0
- database_smartools/database/oracle_extend.py +27 -0
- database_smartools/database/postgre_extend.py +396 -0
- database_smartools/main.py +86 -0
- database_smartools/module/__init__.py +18 -0
- database_smartools/module/function.py +115 -0
- database_smartools/utils/__init__.py +18 -0
- database_smartools/utils/config.py +56 -0
- database_smartools/utils/debug.py +59 -0
- database_smartools/utils/file.py +42 -0
- database_smartools/utils/http.py +74 -0
- database_smartools/utils/logger.py +237 -0
- database_smartools/utils/output.py +31 -0
- database_smartools/utils/texter.py +186 -0
- database_smartools/utils/timer.py +52 -0
- database_smartools-0.0.1.dist-info/METADATA +80 -0
- database_smartools-0.0.1.dist-info/RECORD +27 -0
- database_smartools-0.0.1.dist-info/WHEEL +5 -0
- database_smartools-0.0.1.dist-info/licenses/LICENSE +13 -0
- database_smartools-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,396 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : python-main
|
4
|
+
@文件名称 : postgre_extend.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/6/7 19:06
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
|
12
|
+
from sqlalchemy import create_engine
|
13
|
+
import cx_Oracle
|
14
|
+
from utils import config, logger, texter
|
15
|
+
import numpy as np
|
16
|
+
|
17
|
+
# 获取数据池
|
18
|
+
cx_Oracle.init_oracle_client(lib_dir=config.MAP['db_lib']) # 替换为你的Instant Client路径
|
19
|
+
POOL_MAP = {}
|
20
|
+
|
21
|
+
|
22
|
+
def get_pool():
|
23
|
+
pool = cx_Oracle.SessionPool(user=config.MAP['db_user'],
|
24
|
+
password=config.MAP['db_password'],
|
25
|
+
dsn=cx_Oracle.makedsn(config.MAP['db_host'], config.MAP['db_port'],
|
26
|
+
config.MAP['db_name']),
|
27
|
+
min=2, max=15, increment=1, threaded=False)
|
28
|
+
return pool
|
29
|
+
|
30
|
+
|
31
|
+
def get_pool_by_key(db_key, refresh=False):
|
32
|
+
global POOL_MAP
|
33
|
+
scan_db_conf = f"""
|
34
|
+
SELECT user_name,pass_word,url FROM task_template_data_source WHERE db_key = :db_key
|
35
|
+
"""
|
36
|
+
params = {"db_key": db_key}
|
37
|
+
pool = get_pool()
|
38
|
+
conn, message = get_conn(pool)
|
39
|
+
select_result, select_message = select(conn, scan_db_conf, params)
|
40
|
+
if not select_result:
|
41
|
+
return None, select_message
|
42
|
+
db_conf = select_result['data'][0]
|
43
|
+
user_name = db_conf['user_name']
|
44
|
+
pass_word = db_conf['pass_word']
|
45
|
+
url = db_conf['url']
|
46
|
+
|
47
|
+
url_map = texter.parse_jdbc_url(url)
|
48
|
+
pool = None
|
49
|
+
if db_key not in POOL_MAP.keys() or refresh:
|
50
|
+
if url_map['type'] == 'oracle':
|
51
|
+
try:
|
52
|
+
pool = cx_Oracle.SessionPool(user=user_name,
|
53
|
+
password=pass_word,
|
54
|
+
dsn=cx_Oracle.makedsn(url_map['host'], url_map['port'],
|
55
|
+
url_map['database']),
|
56
|
+
min=2, max=15, increment=1, threaded=False)
|
57
|
+
except Exception as e:
|
58
|
+
message = f"实例化数据库连接池失败,错误信息:{e}"
|
59
|
+
logger.error(message)
|
60
|
+
|
61
|
+
return None, message
|
62
|
+
|
63
|
+
POOL_MAP[db_key] = {
|
64
|
+
"pool": pool,
|
65
|
+
"db_type": url_map['type']
|
66
|
+
}
|
67
|
+
logger.debug(f"创建新的连接池,db_key: {db_key}")
|
68
|
+
else:
|
69
|
+
pool = POOL_MAP[db_key][0]
|
70
|
+
logger.debug(f"使用已有连接池,db_key: {db_key}")
|
71
|
+
return pool, ""
|
72
|
+
|
73
|
+
|
74
|
+
def close_pool(pool):
|
75
|
+
pool.close()
|
76
|
+
logger.debug(f"关闭连接池")
|
77
|
+
|
78
|
+
|
79
|
+
def get_conn(pool):
|
80
|
+
message = ""
|
81
|
+
try:
|
82
|
+
conn = pool.acquire()
|
83
|
+
logger.debug(f"从连接池中获取数据库连接")
|
84
|
+
return conn, message
|
85
|
+
except Exception as e:
|
86
|
+
message = f'获取数据连接异常,错误信息:{e}'
|
87
|
+
logger.error(f'获取数据连接异常,错误信息:{e}')
|
88
|
+
return None, message
|
89
|
+
|
90
|
+
|
91
|
+
def get_conn_map(pool_map):
|
92
|
+
message = ""
|
93
|
+
try:
|
94
|
+
conn = pool_map['pool'].acquire()
|
95
|
+
db_type = pool_map['db_type']
|
96
|
+
conn_map = {
|
97
|
+
"conn": conn,
|
98
|
+
"db_type": db_type
|
99
|
+
}
|
100
|
+
logger.debug(f"从连接池中获取数据库连接和数据库类型")
|
101
|
+
return conn_map, message
|
102
|
+
except Exception as e:
|
103
|
+
message = f'获取数据连接异常,错误信息:{e}'
|
104
|
+
logger.error(f'获取数据连接异常,错误信息:{e}')
|
105
|
+
return None, message
|
106
|
+
|
107
|
+
|
108
|
+
def get_engine():
|
109
|
+
url = f'oracle+cx_oracle://{config.DB_USER}:{config.DB_PASSWORD}@{config.DB_HOST}:{config.DB_PORT}/?service_name={config.DB_NAME}'
|
110
|
+
engine = create_engine(url,
|
111
|
+
pool_size=30,
|
112
|
+
max_overflow=20,
|
113
|
+
pool_timeout=30,
|
114
|
+
pool_recycle=1800,
|
115
|
+
pool_pre_ping=True)
|
116
|
+
|
117
|
+
return engine
|
118
|
+
|
119
|
+
|
120
|
+
def close_engine(engine):
|
121
|
+
engine.dispose()
|
122
|
+
|
123
|
+
|
124
|
+
def close_conn(pool, conn):
|
125
|
+
if isinstance(pool, dict):
|
126
|
+
pool = pool['pool']
|
127
|
+
|
128
|
+
if isinstance(conn, dict):
|
129
|
+
conn = conn['conn']
|
130
|
+
pool.release(conn)
|
131
|
+
logger.debug(f"从连接池中释放数据库连接")
|
132
|
+
return conn
|
133
|
+
|
134
|
+
|
135
|
+
def commit(conn):
|
136
|
+
if isinstance(conn, dict):
|
137
|
+
conn = conn['conn']
|
138
|
+
conn.commit()
|
139
|
+
logger.debug(f"数据库连接-提交事务")
|
140
|
+
return
|
141
|
+
|
142
|
+
|
143
|
+
def rollback(conn):
|
144
|
+
if isinstance(conn, dict):
|
145
|
+
conn = conn['conn']
|
146
|
+
conn.rollback()
|
147
|
+
logger.debug(f"数据库连接-回滚事务")
|
148
|
+
return
|
149
|
+
|
150
|
+
|
151
|
+
def select(conn, sql, params=None):
|
152
|
+
result = None
|
153
|
+
message = ""
|
154
|
+
with conn.cursor() as cursor:
|
155
|
+
try:
|
156
|
+
if params:
|
157
|
+
rs = cursor.execute(sql, params).fetchall()
|
158
|
+
result = {
|
159
|
+
'data': rs,
|
160
|
+
'desc': cursor.description
|
161
|
+
}
|
162
|
+
else:
|
163
|
+
rs = cursor.execute(sql).fetchall()
|
164
|
+
result = {
|
165
|
+
'data': rs,
|
166
|
+
'desc': cursor.description
|
167
|
+
}
|
168
|
+
|
169
|
+
logger.debug(f"[数据查询]sql: {sql}, 参数列表: {params}")
|
170
|
+
|
171
|
+
except Exception as e:
|
172
|
+
message = f"[数据查询]异常:{e}"
|
173
|
+
logger.error(message)
|
174
|
+
return None, message
|
175
|
+
|
176
|
+
# print(result)
|
177
|
+
data = []
|
178
|
+
for row in result['data']:
|
179
|
+
item_map = {}
|
180
|
+
for index, item in enumerate(row):
|
181
|
+
if result['desc'][index][1] == cx_Oracle.DATETIME and item is not None:
|
182
|
+
item = item.strftime("%Y-%m-%d %H:%M:%S")
|
183
|
+
|
184
|
+
item_map[result['desc'][index][0].lower()] = item
|
185
|
+
data.append(item_map)
|
186
|
+
result['data'] = data
|
187
|
+
return result, message
|
188
|
+
|
189
|
+
|
190
|
+
def select_by_map(conn_map, sql, params=None):
|
191
|
+
result = None
|
192
|
+
message = ""
|
193
|
+
conn = conn_map['conn']
|
194
|
+
with conn.cursor() as cursor:
|
195
|
+
try:
|
196
|
+
if params:
|
197
|
+
rs = cursor.execute(sql, params).fetchall()
|
198
|
+
result = {
|
199
|
+
'data': rs,
|
200
|
+
'desc': cursor.description
|
201
|
+
}
|
202
|
+
else:
|
203
|
+
rs = cursor.execute(sql).fetchall()
|
204
|
+
result = {
|
205
|
+
'data': rs,
|
206
|
+
'desc': cursor.description
|
207
|
+
}
|
208
|
+
|
209
|
+
logger.debug(f"[数据查询]sql: {sql}, 参数列表: {params}")
|
210
|
+
|
211
|
+
column_types = []
|
212
|
+
for desc in result['desc']:
|
213
|
+
column_types.append(desc[1])
|
214
|
+
result['data_types'] = column_types
|
215
|
+
|
216
|
+
except Exception as e:
|
217
|
+
message = f"[数据查询]异常:{e}"
|
218
|
+
logger.error(message)
|
219
|
+
return None, message
|
220
|
+
|
221
|
+
# print(result)
|
222
|
+
data = []
|
223
|
+
for row in result['data']:
|
224
|
+
item_map = {}
|
225
|
+
for index, item in enumerate(row):
|
226
|
+
# if result['desc'][index][1] == cx_Oracle.DATETIME and item is not None:
|
227
|
+
# item = item.strftime("%Y-%m-%d")
|
228
|
+
|
229
|
+
if result['desc'][index][1] == cx_Oracle.TIMESTAMP and item is not None:
|
230
|
+
item = item.strftime("%Y-%m-%d %H:%M:%S")
|
231
|
+
|
232
|
+
item_map[result['desc'][index][0].lower()] = item
|
233
|
+
|
234
|
+
data.append(item_map)
|
235
|
+
result['data'] = data
|
236
|
+
return result, message
|
237
|
+
|
238
|
+
|
239
|
+
def delete(conn, sql, params=None):
|
240
|
+
message = ""
|
241
|
+
with conn.cursor() as cursor:
|
242
|
+
try:
|
243
|
+
if params:
|
244
|
+
cursor.execute(sql, params)
|
245
|
+
else:
|
246
|
+
cursor.execute(sql)
|
247
|
+
|
248
|
+
logger.debug(f"[数据删除]sql: {sql}, 参数列表: {params}")
|
249
|
+
except Exception as e:
|
250
|
+
message = f"[数据删除]异常:{e}"
|
251
|
+
logger.error(message)
|
252
|
+
return False, message
|
253
|
+
|
254
|
+
return True, message
|
255
|
+
|
256
|
+
|
257
|
+
def delete_by_map(conn_map, sql, params=None):
|
258
|
+
message = ""
|
259
|
+
conn = conn_map['conn']
|
260
|
+
with conn.cursor() as cursor:
|
261
|
+
try:
|
262
|
+
if params:
|
263
|
+
cursor.execute(sql, params)
|
264
|
+
else:
|
265
|
+
cursor.execute(sql)
|
266
|
+
|
267
|
+
logger.debug(f"[数据删除]sql: {sql}, 参数列表: {params}")
|
268
|
+
except Exception as e:
|
269
|
+
message = f"[数据删除]异常:{e}"
|
270
|
+
logger.error(message)
|
271
|
+
return False, message
|
272
|
+
|
273
|
+
return True, message
|
274
|
+
|
275
|
+
|
276
|
+
def update(conn, sql, params=None):
|
277
|
+
message = ""
|
278
|
+
with conn.cursor() as cursor:
|
279
|
+
try:
|
280
|
+
if params:
|
281
|
+
cursor.execute(sql, params)
|
282
|
+
else:
|
283
|
+
cursor.execute(sql)
|
284
|
+
|
285
|
+
logger.debug(f"[数据更新]sql: {sql}, 参数列表: {params}")
|
286
|
+
except Exception as e:
|
287
|
+
message = f"[数据更新]异常:{e}"
|
288
|
+
logger.error(message)
|
289
|
+
return False, message
|
290
|
+
return True, message
|
291
|
+
|
292
|
+
|
293
|
+
def update_by_map(conn_map, sql, params=None):
|
294
|
+
message = ""
|
295
|
+
conn = conn_map['conn']
|
296
|
+
with conn.cursor() as cursor:
|
297
|
+
try:
|
298
|
+
if params:
|
299
|
+
cursor.execute(sql, params)
|
300
|
+
else:
|
301
|
+
cursor.execute(sql)
|
302
|
+
|
303
|
+
logger.debug(f"[数据更新]sql: {sql}, 参数列表: {params}")
|
304
|
+
except Exception as e:
|
305
|
+
message = f"[数据更新]异常:{e}"
|
306
|
+
logger.info(message)
|
307
|
+
return False, message
|
308
|
+
return True, message
|
309
|
+
|
310
|
+
|
311
|
+
def insert(conn, sql, params=None):
|
312
|
+
message = ""
|
313
|
+
with conn.cursor() as cursor:
|
314
|
+
try:
|
315
|
+
if params:
|
316
|
+
cursor.execute(sql, params)
|
317
|
+
else:
|
318
|
+
cursor.execute(sql)
|
319
|
+
|
320
|
+
logger.debug(f"[数据库新增]sql: {sql}, 参数列表: {params}")
|
321
|
+
|
322
|
+
except Exception as e:
|
323
|
+
message = f"[数据库新增]异常:{e}"
|
324
|
+
logger.error(message)
|
325
|
+
return False, message
|
326
|
+
|
327
|
+
return True, message
|
328
|
+
|
329
|
+
|
330
|
+
def insert_by_map(conn_map, sql, params=None):
|
331
|
+
message = ""
|
332
|
+
conn = conn_map['conn']
|
333
|
+
with conn.cursor() as cursor:
|
334
|
+
try:
|
335
|
+
if params:
|
336
|
+
cursor.execute(sql, params)
|
337
|
+
else:
|
338
|
+
cursor.execute(sql)
|
339
|
+
|
340
|
+
logger.debug(f"[数据库新增]sql: {sql}, 参数列表: {params}")
|
341
|
+
|
342
|
+
except Exception as e:
|
343
|
+
message = f"[数据库新增]异常:{e}"
|
344
|
+
logger.error(message)
|
345
|
+
return False, message
|
346
|
+
|
347
|
+
return True, message
|
348
|
+
|
349
|
+
|
350
|
+
def insert_by_dataframe(conn_map, df, table_name):
|
351
|
+
message = ""
|
352
|
+
conn = conn_map
|
353
|
+
if isinstance(conn_map, dict):
|
354
|
+
conn = conn_map['conn']
|
355
|
+
|
356
|
+
columns = df.columns.tolist() # 获得dataframe的列名
|
357
|
+
data_to_insert = [tuple(row) for row in df.to_numpy()] # dataframe转换numpy
|
358
|
+
print(data_to_insert)
|
359
|
+
with conn.cursor() as cursor:
|
360
|
+
try:
|
361
|
+
sql = df_insert2db(columns, save_table_name=table_name)
|
362
|
+
logger.debug(f"[数据库新增][dataframe]sql: {sql}")
|
363
|
+
batch_size = int(config.MAP['batch_size'])
|
364
|
+
for i in range(0, len(data_to_insert), batch_size):
|
365
|
+
batch_data = data_to_insert[i: i + batch_size]
|
366
|
+
print(batch_data)
|
367
|
+
logger.debug(f"[分批写入][dataframe]当前载入至第{min(i + batch_size, len(data_to_insert))}行。")
|
368
|
+
cursor.executemany(sql, batch_data)
|
369
|
+
conn.commit() # 批量执行query_sql, 每批次提交一次
|
370
|
+
|
371
|
+
except Exception as e:
|
372
|
+
message = f"[数据库新增][dataframe]异常:{e}"
|
373
|
+
logger.error(message)
|
374
|
+
conn.rollback()
|
375
|
+
return False, message
|
376
|
+
|
377
|
+
return True, message
|
378
|
+
|
379
|
+
|
380
|
+
def df_insert2db(columns, save_table_name):
|
381
|
+
"""
|
382
|
+
Args:
|
383
|
+
columns: 以列表的形式
|
384
|
+
save_table_name: 保存table的名字
|
385
|
+
Returns:直接的insert到Oracle的sql语句,字符串格式
|
386
|
+
"""
|
387
|
+
s = ''
|
388
|
+
for i in range(len(columns)):
|
389
|
+
s = s + columns[i] + '-'
|
390
|
+
sql_columns = s.replace('-', ',')[:-1] # 不要最后输出的逗号
|
391
|
+
sql_number_str = ''
|
392
|
+
for i in range(1, len(columns) + 1, 1):
|
393
|
+
sql_number_str = sql_number_str + ':' + str(i) + ',' # ':1,:2,:3,:4,:5,:6'
|
394
|
+
sql_number_str = sql_number_str[:-1]
|
395
|
+
query_sql = 'insert into ' + save_table_name + '(' + sql_columns + ') values(' + sql_number_str + ') '
|
396
|
+
return query_sql
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : python-main
|
4
|
+
@文件名称 : main.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/6/7 19:06
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
import multiprocessing
|
12
|
+
|
13
|
+
import uvicorn
|
14
|
+
import sys
|
15
|
+
from fastapi import FastAPI, Request
|
16
|
+
from utils import config, file, logger, http, texter, output, timer
|
17
|
+
from api import etl
|
18
|
+
import os
|
19
|
+
|
20
|
+
app = FastAPI()
|
21
|
+
env = "dev"
|
22
|
+
res_dir = os.path.dirname(__file__)
|
23
|
+
|
24
|
+
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
25
|
+
BASE_DIR = os.path.dirname(res_dir)
|
26
|
+
print("当前工作路径:", BASE_DIR)
|
27
|
+
else:
|
28
|
+
BASE_DIR = os.path.dirname(__file__)
|
29
|
+
print("当前工作路径:", BASE_DIR)
|
30
|
+
|
31
|
+
workspace = BASE_DIR
|
32
|
+
@app.get("/")
|
33
|
+
def read_root(request: Request):
|
34
|
+
return
|
35
|
+
|
36
|
+
@app.post("/logRefresh")
|
37
|
+
def refresh_log():
|
38
|
+
logger.Logger()._check_and_rotate_log(refresh=True)
|
39
|
+
return http.ResponseUtil.success()
|
40
|
+
|
41
|
+
@app.post("/configRefresh")
|
42
|
+
def refresh_config():
|
43
|
+
config.Config(res_dir + '/conf.ini', 'UTF-8', env)
|
44
|
+
config.add_conf('env', env)
|
45
|
+
config.add_conf('root', workspace)
|
46
|
+
logger.Logger()._check_and_rotate_log(refresh=True)
|
47
|
+
return http.ResponseUtil.success()
|
48
|
+
|
49
|
+
# uvicorn提供服务化
|
50
|
+
if __name__ == '__main__':
|
51
|
+
print(
|
52
|
+
rf"""
|
53
|
+
__ __ _ _ _____ ___ _ _
|
54
|
+
\ \ / /| | | || ___||_ _|| \ | |
|
55
|
+
\ V / | |_| || |_ | | | \| |
|
56
|
+
| | | _ || _| | | | |\ |
|
57
|
+
|_| |_| |_||_| |___||_| \_|
|
58
|
+
@项目名称 : python-main
|
59
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
60
|
+
"""
|
61
|
+
)
|
62
|
+
multiprocessing.freeze_support() # 使用pyinstaller打包后,如果不加这行代码,并行处理会出问题
|
63
|
+
argv = sys.argv
|
64
|
+
env = 'dev'
|
65
|
+
if len(argv) > 1:
|
66
|
+
env = argv[1]
|
67
|
+
|
68
|
+
cf = config.Config(res_dir + '/conf.ini', 'UTF-8', env)
|
69
|
+
config.add_conf('env', env)
|
70
|
+
config.add_conf('root', workspace)
|
71
|
+
host = config.MAP['server_host'] if config.MAP['server_host'] != '0.0.0.0' else http.get_local_ip()
|
72
|
+
port = int(config.MAP['server_port'])
|
73
|
+
logger.Logger()
|
74
|
+
from database import db_handler as dh
|
75
|
+
dh._init_lib()
|
76
|
+
dh._init_local_db()
|
77
|
+
logger.debug(f"初始化oracle lib")
|
78
|
+
logger.debug(f"----- 工作路径:{workspace} -----")
|
79
|
+
logger.debug(f"----- 服务器启动,连接地址 http://{host}:{port} -----")
|
80
|
+
logger.debug(f"----- Swagger UI,连接地址 http://{host}:{port}/docs -----")
|
81
|
+
|
82
|
+
from api import etl
|
83
|
+
|
84
|
+
app.include_router(etl.router, prefix="/etl", tags=["ETL工具"])
|
85
|
+
|
86
|
+
uvicorn.run(app, host=host, port=port)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : yhfin-data-agent
|
4
|
+
@文件名称 : __init__.py.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/9/9 17:02
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
def test():
|
14
|
+
print()
|
15
|
+
|
16
|
+
|
17
|
+
if __name__ == '__main__':
|
18
|
+
None
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : python-main
|
4
|
+
@文件名称 : function.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/6/7 19:06
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
|
12
|
+
import importlib
|
13
|
+
import os.path
|
14
|
+
import sys
|
15
|
+
from pathlib import Path
|
16
|
+
from utils import logger, config, file, timer
|
17
|
+
|
18
|
+
|
19
|
+
def execute_function(func_name, args=None, script_dir=None):
|
20
|
+
"""
|
21
|
+
通过函数名动态执行对应脚本中的函数
|
22
|
+
|
23
|
+
:param func_name: 要执行的函数名称
|
24
|
+
:param args: 函数传入的参数
|
25
|
+
:param script_dir: 存放函数脚本的目录,默认为conf.ini -> common -> script_dir
|
26
|
+
"""
|
27
|
+
result = {
|
28
|
+
'status': False,
|
29
|
+
'data': {},
|
30
|
+
'message': f"函数{func_name}运行时发生错误,未知异常",
|
31
|
+
'time': 0
|
32
|
+
}
|
33
|
+
# 获取函数脚本目录的绝对路径
|
34
|
+
base_dir = config.MAP['root'] # 当前项目所在目录
|
35
|
+
target_dir = os.path.join(base_dir, config.MAP['script_dir'])
|
36
|
+
if script_dir:
|
37
|
+
target_dir = script_dir
|
38
|
+
# 临时添加目标目录到sys.path
|
39
|
+
original_sys_path = sys.path.copy()
|
40
|
+
start_time = timer.get_time()
|
41
|
+
try:
|
42
|
+
|
43
|
+
root, filename = file.search_script(target_dir, func_name + '.py')
|
44
|
+
if not root:
|
45
|
+
end_time = timer.get_time()
|
46
|
+
message = f"错误:找不到名为'{func_name}'的脚本。"
|
47
|
+
logger.error(message)
|
48
|
+
result['status'] = False
|
49
|
+
result['message'] = message
|
50
|
+
result['time'] = timer.get_timediff(end_time, start_time)
|
51
|
+
return result
|
52
|
+
|
53
|
+
sys.path.insert(0, str(root))
|
54
|
+
|
55
|
+
try:
|
56
|
+
# 动态导入模块
|
57
|
+
module = importlib.import_module(func_name)
|
58
|
+
|
59
|
+
# 获取函数对象
|
60
|
+
func = getattr(module, func_name)
|
61
|
+
logger.debug(f"获取函数对象,module: {module}, func_name: {func_name}")
|
62
|
+
|
63
|
+
# 执行函数
|
64
|
+
rtn_map = None
|
65
|
+
logger.debug(f"运行函数,func_name: {func_name}")
|
66
|
+
if args:
|
67
|
+
rtn_map = func(args)
|
68
|
+
else:
|
69
|
+
rtn_map = func()
|
70
|
+
end_time = timer.get_time()
|
71
|
+
dur_time = timer.get_timediff(end_time, start_time)
|
72
|
+
result['time'] = dur_time
|
73
|
+
logger.debug(f"函数运行结束,运行时间: {dur_time}")
|
74
|
+
if rtn_map is not None:
|
75
|
+
result['status'] = rtn_map['result']
|
76
|
+
if 'data' in rtn_map.keys():
|
77
|
+
result['data'] = rtn_map['data']
|
78
|
+
result['message'] = rtn_map['message']
|
79
|
+
|
80
|
+
except ImportError as e:
|
81
|
+
end_time = timer.get_time()
|
82
|
+
message = f"脚本'{func_name}'导入异常。错误信息:{e}"
|
83
|
+
logger.error(message)
|
84
|
+
result['status'] = False
|
85
|
+
result['message'] = message
|
86
|
+
result['time'] = timer.get_timediff(end_time, start_time)
|
87
|
+
|
88
|
+
except AttributeError as e:
|
89
|
+
end_time = timer.get_time()
|
90
|
+
message = f"函数{func_name}运行时发生错误,错误信息:{e}。"
|
91
|
+
logger.error(message)
|
92
|
+
result['status'] = False
|
93
|
+
result['message'] = message
|
94
|
+
result['time'] = timer.get_timediff(end_time, start_time)
|
95
|
+
|
96
|
+
finally:
|
97
|
+
# 从 sys.modules 中移除已导入的模块
|
98
|
+
if func_name in sys.modules:
|
99
|
+
del sys.modules[func_name]
|
100
|
+
# 从 sys.path 中移除临时添加的路径
|
101
|
+
if str(root) in sys.path:
|
102
|
+
sys.path.remove(str(root))
|
103
|
+
|
104
|
+
except Exception as e:
|
105
|
+
end_time = timer.get_time()
|
106
|
+
message = f"函数{func_name}运行时发生错误,错误信息:{e}。"
|
107
|
+
logger.error(message)
|
108
|
+
result['status'] = False
|
109
|
+
result['message'] = message
|
110
|
+
result['time'] = timer.get_timediff(end_time, start_time)
|
111
|
+
|
112
|
+
finally:
|
113
|
+
# 恢复原始sys.path
|
114
|
+
sys.path = original_sys_path
|
115
|
+
return result
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : yhfin-data-agent
|
4
|
+
@文件名称 : __init__.py.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/9/9 17:02
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
|
12
|
+
|
13
|
+
def test():
|
14
|
+
print()
|
15
|
+
|
16
|
+
|
17
|
+
if __name__ == '__main__':
|
18
|
+
None
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
@项目名称 : python-main
|
4
|
+
@文件名称 : config.py
|
5
|
+
@创建人 : zhongbinjie
|
6
|
+
@创建时间 : 2025/6/7 19:06
|
7
|
+
@文件说明 :
|
8
|
+
@企业名称 : 深圳市赢和信息技术有限公司
|
9
|
+
@Copyright:2025-2035, 深圳市赢和信息技术有限公司. All rights Reserved.
|
10
|
+
"""
|
11
|
+
|
12
|
+
import configparser
|
13
|
+
|
14
|
+
MAP = {}
|
15
|
+
|
16
|
+
def add_conf(key, value):
|
17
|
+
global MAP
|
18
|
+
MAP[key] = value
|
19
|
+
|
20
|
+
class Config(object):
|
21
|
+
env : str
|
22
|
+
def __init__(self, filename, encoding, env):
|
23
|
+
print("初始化配置信息")
|
24
|
+
global MAP
|
25
|
+
MAP = {}
|
26
|
+
# 声明配置类对象
|
27
|
+
self.config = configparser.ConfigParser()
|
28
|
+
# 读取配置文件
|
29
|
+
self.config.read(filename, encoding)
|
30
|
+
|
31
|
+
try:
|
32
|
+
items = self.get_items('common')
|
33
|
+
for key, conf in items:
|
34
|
+
setattr(self, key, conf)
|
35
|
+
|
36
|
+
items = self.get_items(env)
|
37
|
+
for key, conf in items:
|
38
|
+
setattr(self, key, conf)
|
39
|
+
if key == 'biz_db_type':
|
40
|
+
db_confs = self.get_items(conf)
|
41
|
+
for key, conf in db_confs:
|
42
|
+
setattr(self, key, conf)
|
43
|
+
|
44
|
+
MAP = self.__dict__
|
45
|
+
# print("配置对象属性", MAP)
|
46
|
+
except Exception as e:
|
47
|
+
print(e)
|
48
|
+
|
49
|
+
def get_options(self, section):
|
50
|
+
"""获取 option"""
|
51
|
+
return self.config.options(section)
|
52
|
+
|
53
|
+
def get_items(self, section):
|
54
|
+
"""获取 items"""
|
55
|
+
return self.config.items(section)
|
56
|
+
|