mdbq 4.0.5__tar.gz → 4.0.7__tar.gz
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.
- {mdbq-4.0.5 → mdbq-4.0.7}/PKG-INFO +1 -1
- mdbq-4.0.7/mdbq/__version__.py +1 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/aggregation/query_data.py +17 -142
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/unique_.py +8 -8
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/uploader.py +119 -33
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq.egg-info/PKG-INFO +1 -1
- mdbq-4.0.5/mdbq/__version__.py +0 -1
- {mdbq-4.0.5 → mdbq-4.0.7}/README.txt +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/aggregation/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/config/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/config/config.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/log/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/log/mylogger.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/log/spider_logging.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/deduplicator.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/mysql.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/mysql/s_query.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/other/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/other/download_sku_picture.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/other/otk.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/other/pov_city.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/other/ua_sj.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/pbix/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/pbix/pbix_refresh.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/pbix/refresh_all.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/redis/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/redis/getredis.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/spider/__init__.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq/spider/aikucun.py +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq.egg-info/SOURCES.txt +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq.egg-info/dependency_links.txt +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/mdbq.egg-info/top_level.txt +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/setup.cfg +0 -0
- {mdbq-4.0.5 → mdbq-4.0.7}/setup.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
VERSION = '4.0.7'
|
@@ -180,21 +180,18 @@ class MysqlDatasQuery:
|
|
180
180
|
从数据库中下载数据
|
181
181
|
"""
|
182
182
|
def __init__(self, download_manager):
|
183
|
-
# target_service 从哪个服务器下载数据
|
184
183
|
self.months = 0 # 下载几个月数据, 0 表示当月, 1 是上月 1 号至今
|
185
184
|
self.download_manager = download_manager
|
186
|
-
self.update_service = True # 调试时加,true: 将数据写入 mysql 服务器
|
187
185
|
self.pf_datas = []
|
188
|
-
self.pf_datas_jd = [] # 京东聚合销售表
|
189
186
|
|
190
187
|
@staticmethod
|
191
|
-
def try_except(func):
|
188
|
+
def try_except(func):
|
192
189
|
@wraps(func)
|
193
190
|
def wrapper(*args, **kwargs):
|
194
191
|
try:
|
195
192
|
return func(*args, **kwargs)
|
196
193
|
except Exception as e:
|
197
|
-
logger.info('函数执行错误', {'函数': func.__name__, '错误': str(e)})
|
194
|
+
logger.info('函数执行错误', {'函数': func.__name__, '错误': str(e), 'args': args, 'kwargs': kwargs})
|
198
195
|
|
199
196
|
return wrapper
|
200
197
|
|
@@ -227,7 +224,6 @@ class MysqlDatasQuery:
|
|
227
224
|
)
|
228
225
|
__res.append(df)
|
229
226
|
df = pd.concat(__res, ignore_index=True)
|
230
|
-
|
231
227
|
df.rename(columns={
|
232
228
|
'场景名字': '营销场景',
|
233
229
|
'主体id': '商品id',
|
@@ -235,7 +231,6 @@ class MysqlDatasQuery:
|
|
235
231
|
'总成交笔数': '成交笔数',
|
236
232
|
'总成交金额': '成交金额'
|
237
233
|
}, inplace=True)
|
238
|
-
|
239
234
|
df = df.astype({
|
240
235
|
'商品id': str,
|
241
236
|
'花费': 'float64',
|
@@ -273,7 +268,7 @@ class MysqlDatasQuery:
|
|
273
268
|
'直接成交金额': ('直接成交金额', np.max)
|
274
269
|
}
|
275
270
|
)
|
276
|
-
df.insert(loc=1, column='推广渠道', value='万相台无界版')
|
271
|
+
df.insert(loc=1, column='推广渠道', value='万相台无界版')
|
277
272
|
set_typ = {
|
278
273
|
'日期': 'date',
|
279
274
|
'推广渠道': 'varchar(100)',
|
@@ -290,7 +285,7 @@ class MysqlDatasQuery:
|
|
290
285
|
'直接成交笔数': 'int',
|
291
286
|
'直接成交金额': 'decimal(12,2)',
|
292
287
|
}
|
293
|
-
|
288
|
+
# 制作其他聚合表
|
294
289
|
self.pf_datas.append(
|
295
290
|
{
|
296
291
|
'集合名称': '天猫汇总表调用',
|
@@ -298,7 +293,7 @@ class MysqlDatasQuery:
|
|
298
293
|
['日期', '店铺名称', '推广渠道', '营销场景', '商品id', '花费', '展现量', '点击量', '加购量',
|
299
294
|
'成交笔数', '成交金额', '直接成交笔数', '直接成交金额', '自然流量曝光量']]
|
300
295
|
}
|
301
|
-
)
|
296
|
+
)
|
302
297
|
logger.info('正在更新数据库', {'主机': f'{host}:{port}', '库': db_name, '表': table_name})
|
303
298
|
uld.upload_data(
|
304
299
|
db_name=db_name,
|
@@ -720,23 +715,11 @@ class MysqlDatasQuery:
|
|
720
715
|
__res.append(df)
|
721
716
|
df = pd.concat(__res, ignore_index=True)
|
722
717
|
df['宝贝id'] = df['宝贝id'].astype(str)
|
723
|
-
# df = df.groupby(['日期', '店铺名称', '宝贝id', '行业类目'], as_index=False).agg(
|
724
|
-
# **{
|
725
|
-
# '销售额': ('销售额', np.min),
|
726
|
-
# '销售量': ('销售量', np.min),
|
727
|
-
# '订单数': ('订单数', np.min),
|
728
|
-
# '退货量': ('退货量', np.max),
|
729
|
-
# '退款额': ('退款额', np.max),
|
730
|
-
# '退款额_发货后': ('退款额_发货后', np.max),
|
731
|
-
# '退货量_发货后': ('退货量_发货后', np.max),
|
732
|
-
# }
|
733
|
-
# )
|
734
718
|
# 仅保留最新日期的数据
|
735
719
|
idx = df.groupby(['日期', '店铺名称', '宝贝id'])['更新时间'].idxmax()
|
736
720
|
df = df.loc[idx]
|
737
721
|
df = df[['日期', '店铺名称', '宝贝id', '行业类目', '销售额', '销售量', '订单数', '退货量', '退款额', '退款额_发货后', '退货量_发货后']]
|
738
|
-
df['件均价'] =
|
739
|
-
0) # 两列运算, 避免除以0
|
722
|
+
df['件均价'] = np.where(df['销售量'] > 0, df['销售额'] / df['销售量'], 0).round(0)
|
740
723
|
df['价格带'] = df['件均价'].apply(
|
741
724
|
lambda x: '2000+' if x >= 2000
|
742
725
|
else '1000+' if x >= 1000
|
@@ -850,8 +833,7 @@ class MysqlDatasQuery:
|
|
850
833
|
'直接成交金额': ('直接成交金额', np.max)
|
851
834
|
}
|
852
835
|
)
|
853
|
-
df.insert(loc=1, column='推广渠道', value='万相台无界版')
|
854
|
-
|
836
|
+
df.insert(loc=1, column='推广渠道', value='万相台无界版')
|
855
837
|
# 开始处理用户特征
|
856
838
|
df_sx = self.download_manager.data_to_df(
|
857
839
|
db_name='达摩盘3',
|
@@ -860,7 +842,7 @@ class MysqlDatasQuery:
|
|
860
842
|
end_date=end_date,
|
861
843
|
projection={'人群名称': 1, '消费能力等级': 1, '用户年龄': 1},
|
862
844
|
)
|
863
|
-
df_sx['人群名称'] = df_sx['人群名称']
|
845
|
+
df_sx['人群名称'] = '达摩盘:' + df_sx['人群名称']
|
864
846
|
df_sx.rename(columns={'消费能力等级': '消费力层级'}, inplace=True)
|
865
847
|
df = pd.merge(df, df_sx, left_on=['人群名字'], right_on=['人群名称'], how='left')
|
866
848
|
df.pop('人群名称')
|
@@ -869,10 +851,8 @@ class MysqlDatasQuery:
|
|
869
851
|
df['用户年龄'] = df['用户年龄'].apply(
|
870
852
|
lambda x: "~".join(re.findall(r'(\d{2})\D.*(\d{2})岁', str(x))[0])
|
871
853
|
if str(x) != 'nan' and re.findall(r'(\d{2})\D.*(\d{2})岁', str(x)) else x)
|
872
|
-
|
873
854
|
# 1. 匹配 L后面接 2 个或以上数字,不区分大小写,示例:L345
|
874
855
|
# 2. 其余情况,L 后面接多个数字的都会被第一条 if 命中,不区分大小写
|
875
|
-
|
876
856
|
df['消费力层级'] = df.apply(
|
877
857
|
lambda x:
|
878
858
|
''.join(re.findall(r'(l\d+)', x['人群名字'].upper(), re.IGNORECASE))
|
@@ -883,12 +863,10 @@ class MysqlDatasQuery:
|
|
883
863
|
else 'L2' if re.findall(r'(l\d*2)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
|
884
864
|
else 'L1' if re.findall(r'(l\d*1)', x['人群名字'], re.IGNORECASE) and str(x['消费力层级']) == 'nan'
|
885
865
|
else x['消费力层级'], axis=1)
|
886
|
-
|
887
866
|
# 1. 匹配连续的 4 个数字且后面不能接数字或"元"或汉字,筛掉的人群示例:月均消费6000元|受众20240729175213|xxx2024真皮公文包
|
888
867
|
# 2. 匹配 2数字_2数字且前面不能是数字,合法匹配:人群_30_50_促; 非法示例:L345_3040 避免识别出 35~20 岁用户的情况
|
889
868
|
# pattern = r'(\d{4})(?!\d|[\u4e00-\u9fa5])' # 匹配 4 个数字,后面不能接数字或汉字
|
890
869
|
# pattern = r'(?<![\d\u4e00-\u9fa5])(\d{4})' # 匹配前面不是数字或汉字的 4 个连续数字
|
891
|
-
|
892
870
|
# 匹配 4 个数字,前面和后面都不能是数字或汉字
|
893
871
|
pattern1 = r'(?<![\d\u4e00-\u9fa5])(\d{4})(?!\d|[\u4e00-\u9fa5])'
|
894
872
|
# 匹配指定字符,前面不能是数字或 l 或 L 开头
|
@@ -909,8 +887,7 @@ class MysqlDatasQuery:
|
|
909
887
|
else x
|
910
888
|
)
|
911
889
|
# 年龄层不能是 0 开头
|
912
|
-
df['用户年龄'] = df['用户年龄'].
|
913
|
-
lambda x: '' if str(x).startswith('0') else x)
|
890
|
+
df['用户年龄'] = np.where(df['用户年龄'].astype(str).str.startswith('0'), '', df['用户年龄'])
|
914
891
|
df['用户年龄'] = df['用户年龄'].apply(
|
915
892
|
lambda x:
|
916
893
|
re.sub(f'~50', '~49' ,str(x)) if '~50' in str(x) else
|
@@ -919,10 +896,6 @@ class MysqlDatasQuery:
|
|
919
896
|
re.sub(r'\d{4}~', '', str(x)) if str(x) != 'nan' else
|
920
897
|
x
|
921
898
|
)
|
922
|
-
# df = df.head(1000)
|
923
|
-
# df.to_csv('/Users/xigua/Downloads/test.csv', index=False, header=True, encoding='utf-8_sig')
|
924
|
-
# breakpoint()
|
925
|
-
|
926
899
|
# 下面是添加人群 AIPL 分类
|
927
900
|
dir_file = f'\\\\192.168.1.198\\时尚事业部\\01.运营部\\0-电商周报-每周五更新\\分类配置文件.xlsx'
|
928
901
|
dir_file2 = '/Volumes/时尚事业部/01.运营部/0-电商周报-每周五更新/分类配置文件.xlsx'
|
@@ -1080,7 +1053,6 @@ class MysqlDatasQuery:
|
|
1080
1053
|
dir_file = dir_file2
|
1081
1054
|
if os.path.isfile(dir_file):
|
1082
1055
|
df_fl = pd.read_excel(dir_file, sheet_name='关键词分类', header=0)
|
1083
|
-
# df_fl.rename(columns={'分类1': '词分类'}, inplace=True)
|
1084
1056
|
df_fl = df_fl[['关键词', '词分类']]
|
1085
1057
|
# 合并并获取词分类信息
|
1086
1058
|
df = pd.merge(df, df_fl, left_on=['词名字_词包名字'], right_on=['关键词'], how='left')
|
@@ -1159,7 +1131,6 @@ class MysqlDatasQuery:
|
|
1159
1131
|
return pd.DataFrame()
|
1160
1132
|
return df
|
1161
1133
|
|
1162
|
-
|
1163
1134
|
@try_except
|
1164
1135
|
@upload_data_decorator()
|
1165
1136
|
def tg_cjzb(self, db_name='聚合数据', table_name='天猫_超级直播', is_maximize=True):
|
@@ -1207,7 +1178,6 @@ class MysqlDatasQuery:
|
|
1207
1178
|
if col not in cjzb_qzt.columns.tolist():
|
1208
1179
|
cjzb_qzt[col] = 0
|
1209
1180
|
df = pd.concat([df, cjzb_qzt], ignore_index=True)
|
1210
|
-
|
1211
1181
|
df.rename(columns={
|
1212
1182
|
'观看次数': '观看次数',
|
1213
1183
|
'总购物车数': '加购量',
|
@@ -1283,7 +1253,6 @@ class MysqlDatasQuery:
|
|
1283
1253
|
'直接成交金额': 'decimal(12,2)',
|
1284
1254
|
}
|
1285
1255
|
logger.info('正在更新数据库', {'主机': f'{host}:{port}', '库': db_name, '表': table_name})
|
1286
|
-
|
1287
1256
|
return df, {
|
1288
1257
|
'db_name': db_name,
|
1289
1258
|
'table_name': table_name,
|
@@ -1406,57 +1375,7 @@ class MysqlDatasQuery:
|
|
1406
1375
|
'partition_date_column': '日期', # 用于分表的日期列名,默认为'日期'
|
1407
1376
|
'indexes': [], # 普通索引列
|
1408
1377
|
'transaction_mode': 'batch', # 事务模式
|
1409
|
-
'unique_keys': [['日期', '推广渠道', '店铺名称', '营销场景', '报表类型']], # 唯一约束列表
|
1410
|
-
}
|
1411
|
-
|
1412
|
-
@try_except
|
1413
|
-
@upload_data_decorator()
|
1414
|
-
def idbm_bak(self, db_name='聚合数据', table_name='商品id编码表'):
|
1415
|
-
""" 用生意经日数据制作商品 id 和编码对照表 """
|
1416
|
-
year = datetime.datetime.today().year
|
1417
|
-
data_values = []
|
1418
|
-
for year in range(2022, year+1):
|
1419
|
-
data_values += self.download_manager.columns_to_list(
|
1420
|
-
db_name='生意经3',
|
1421
|
-
table_name=f'宝贝指标_{year}',
|
1422
|
-
columns_name=['宝贝id', '商家编码', '行业类目'],
|
1423
|
-
)
|
1424
|
-
df = pd.DataFrame(data=data_values)
|
1425
|
-
df['宝贝id'] = df['宝贝id'].astype(str)
|
1426
|
-
df.drop_duplicates(subset='宝贝id', keep='last', inplace=True, ignore_index=True)
|
1427
|
-
# df['行业类目'] = df['行业类目'].apply(lambda x: re.sub(' ', '', x))
|
1428
|
-
try:
|
1429
|
-
df[['一级类目', '二级类目', '三级类目']] = df['行业类目'].str.split(' -> ', expand=True).loc[:, 0:2]
|
1430
|
-
except:
|
1431
|
-
try:
|
1432
|
-
df[['一级类目', '二级类目']] = df['行业类目'].str.split(' -> ', expand=True).loc[:, 0:1]
|
1433
|
-
except:
|
1434
|
-
df['一级类目'] = df['行业类目']
|
1435
|
-
df.drop('行业类目', axis=1, inplace=True)
|
1436
|
-
df.sort_values('宝贝id', ascending=False, inplace=True)
|
1437
|
-
df = df[(df['宝贝id'] != '973') & (df['宝贝id'] != 973) & (df['宝贝id'] != '0')]
|
1438
|
-
set_typ = {
|
1439
|
-
'宝贝id': 'bigint',
|
1440
|
-
'商家编码': 'varchar(100)',
|
1441
|
-
'一级类目': 'varchar(100)',
|
1442
|
-
'二级类目': 'varchar(100)',
|
1443
|
-
'三级类目': 'varchar(100)',
|
1444
|
-
}
|
1445
|
-
logger.info('正在更新数据库', {'主机': f'{host}:{port}', '库': db_name, '表': table_name})
|
1446
|
-
return df, {
|
1447
|
-
'db_name': db_name,
|
1448
|
-
'table_name': table_name,
|
1449
|
-
'set_typ': set_typ,
|
1450
|
-
'primary_keys': [], # 创建唯一主键
|
1451
|
-
'check_duplicate': False, # 检查重复数据
|
1452
|
-
'duplicate_columns': [], # 指定排重的组合键
|
1453
|
-
'update_on_duplicate': True, # 更新旧数据
|
1454
|
-
'allow_null': False, # 允许插入空值
|
1455
|
-
'partition_by': None, # 分表方式
|
1456
|
-
'partition_date_column': '日期', # 用于分表的日期列名,默认为'日期'
|
1457
|
-
'indexes': [], # 普通索引列
|
1458
|
-
'transaction_mode': 'batch', # 事务模式
|
1459
|
-
'unique_keys': [['宝贝id']], # 唯一约束列表
|
1378
|
+
'unique_keys': [['日期', '推广渠道', '店铺名称', '营销场景', '报表类型', '花费', '展现量']], # 唯一约束列表
|
1460
1379
|
}
|
1461
1380
|
|
1462
1381
|
@try_except
|
@@ -1650,9 +1569,6 @@ class MysqlDatasQuery:
|
|
1650
1569
|
end_date=end_date,
|
1651
1570
|
projection=projection,
|
1652
1571
|
)
|
1653
|
-
# df.drop_duplicates(
|
1654
|
-
# subset=['日期', '店铺名称', '商品id', '商品访客数'], keep='last',
|
1655
|
-
# inplace=True, ignore_index=True)
|
1656
1572
|
# 保留最新日期的数据
|
1657
1573
|
idx = df.groupby(['日期', '店铺名称', '商品id'])['更新时间'].idxmax()
|
1658
1574
|
df = df.loc[idx]
|
@@ -1691,7 +1607,6 @@ class MysqlDatasQuery:
|
|
1691
1607
|
df['上市季节'] = df['上市年月'].apply(lambda x: check_jijie(x))
|
1692
1608
|
p = df.pop('上市季节')
|
1693
1609
|
df.insert(loc=9, column='上市季节', value=p)
|
1694
|
-
|
1695
1610
|
set_typ = {
|
1696
1611
|
'商品id': 'BIGINT',
|
1697
1612
|
'店铺名称': 'varchar(100)',
|
@@ -1784,7 +1699,6 @@ class MysqlDatasQuery:
|
|
1784
1699
|
)
|
1785
1700
|
__res.append(df)
|
1786
1701
|
df = pd.concat(__res, ignore_index=True)
|
1787
|
-
# df['日期'] = pd.to_datetime(df['日期'], format='%Y-%m-%d', errors='ignore') # 转换日期列
|
1788
1702
|
df = df.astype({'访客数': 'int64'}, errors='ignore')
|
1789
1703
|
df = df[df['访客数'] > 0]
|
1790
1704
|
df.drop_duplicates(subset=['日期', '店铺名称', '类别', '来源构成', '一级来源', '二级来源', '三级来源', '访客数'], keep='last', inplace=True, ignore_index=True)
|
@@ -1800,7 +1714,6 @@ class MysqlDatasQuery:
|
|
1800
1714
|
df_visitor3['index'] = df_visitor3['index'] + 100
|
1801
1715
|
df_visitor3.rename(columns={'index': '三级来源索引'}, inplace=True)
|
1802
1716
|
df_visitor3 = df_visitor3[['三级来源', '三级来源索引']]
|
1803
|
-
|
1804
1717
|
# 包含二级来源名称和预设索引值列
|
1805
1718
|
df_visitor2 = df[df['日期'] >= pd.to_datetime(last_month)]
|
1806
1719
|
df_visitor2 = df_visitor2[(df_visitor2['二级来源'] != '汇总') & (df_visitor2['二级来源'] != '0')]
|
@@ -1810,7 +1723,6 @@ class MysqlDatasQuery:
|
|
1810
1723
|
df_visitor2['index'] = df_visitor2['index'] + 100
|
1811
1724
|
df_visitor2.rename(columns={'index': '二级来源索引'}, inplace=True)
|
1812
1725
|
df_visitor2 = df_visitor2[['二级来源', '二级来源索引']]
|
1813
|
-
|
1814
1726
|
# 包含一级来源名称和预设索引值列
|
1815
1727
|
df_visitor1 = df[df['日期'] >= pd.to_datetime(last_month)]
|
1816
1728
|
df_visitor1 = df_visitor1[(df_visitor1['一级来源'] != '汇总') & (df_visitor1['一级来源'] != '0')]
|
@@ -1939,7 +1851,6 @@ class MysqlDatasQuery:
|
|
1939
1851
|
projection=projection,
|
1940
1852
|
)
|
1941
1853
|
__res.append(df)
|
1942
|
-
|
1943
1854
|
df = pd.concat(__res, ignore_index=True)
|
1944
1855
|
df = df.groupby(
|
1945
1856
|
['日期', '店铺名称', '产品线', '触发sku_id', '跟单sku_id', 'spu_id', '花费', '展现数', '点击数'],
|
@@ -2201,13 +2112,6 @@ class MysqlDatasQuery:
|
|
2201
2112
|
__res.append(df)
|
2202
2113
|
df = pd.concat(__res, ignore_index=True)
|
2203
2114
|
df = df[df['商品id'] != '合计']
|
2204
|
-
# df = df.groupby(['日期', '店铺名称', '商品id', '货号', '访客数', '成交客户数', '加购商品件数', '加购人数'],
|
2205
|
-
# as_index=False).agg(
|
2206
|
-
# **{
|
2207
|
-
# '成交单量': ('成交单量', np.max),
|
2208
|
-
# '成交金额': ('成交金额', np.max),
|
2209
|
-
# }
|
2210
|
-
# )
|
2211
2115
|
# 仅保留最新日期的数据
|
2212
2116
|
idx = df.groupby(['日期', '店铺名称', '商品id', '货号', '访客数', '成交客户数', '加购商品件数', '加购人数'])['更新时间'].idxmax()
|
2213
2117
|
df = df.loc[idx]
|
@@ -2271,13 +2175,6 @@ class MysqlDatasQuery:
|
|
2271
2175
|
__res.append(df)
|
2272
2176
|
df = pd.concat(__res, ignore_index=True)
|
2273
2177
|
df = df[df['商品id'] != '合计']
|
2274
|
-
# df = df.groupby(['日期', '店铺名称', '商品id', '货号', '访客数', '成交客户数', '加购商品件数', '加购人数'],
|
2275
|
-
# as_index=False).agg(
|
2276
|
-
# **{
|
2277
|
-
# '成交单量': ('成交单量', np.max),
|
2278
|
-
# '成交金额': ('成交金额', np.max),
|
2279
|
-
# }
|
2280
|
-
# )
|
2281
2178
|
# 仅保留最新日期的数据
|
2282
2179
|
idx = df.groupby(['日期', '店铺名称', '商品id', '货号', '访客数', '成交客户数', '加购商品件数', '加购人数'])['更新时间'].idxmax()
|
2283
2180
|
df = df.loc[idx]
|
@@ -2544,7 +2441,6 @@ class MysqlDatasQuery:
|
|
2544
2441
|
df_jd = pd.DataFrame() # 京东推广
|
2545
2442
|
df_jd_qzyx = pd.DataFrame() # 京东全站推广
|
2546
2443
|
df_jd_ziying = pd.DataFrame() # 京东推广
|
2547
|
-
|
2548
2444
|
start_date, end_date = self.months_data(num=self.months)
|
2549
2445
|
projection = {
|
2550
2446
|
'日期': 1,
|
@@ -2659,7 +2555,6 @@ class MysqlDatasQuery:
|
|
2659
2555
|
'成交金额': ('总成交金额', np.max)
|
2660
2556
|
}
|
2661
2557
|
)
|
2662
|
-
|
2663
2558
|
# 天猫的全站推广包含在营销场景报表中,淘宝店不包含
|
2664
2559
|
df_tb_qzt = pd.DataFrame()
|
2665
2560
|
if '全站推广' not in df_tb['营销场景'].tolist():
|
@@ -2711,7 +2606,6 @@ class MysqlDatasQuery:
|
|
2711
2606
|
}
|
2712
2607
|
)
|
2713
2608
|
df_tb_qzt['营销场景'] = '全站推广'
|
2714
|
-
|
2715
2609
|
# 品销宝报表
|
2716
2610
|
projection = {
|
2717
2611
|
'日期': 1,
|
@@ -2750,7 +2644,6 @@ class MysqlDatasQuery:
|
|
2750
2644
|
)
|
2751
2645
|
df_tm_pxb.rename(columns={'报表类型': '营销场景', '消耗': '花费'}, inplace=True)
|
2752
2646
|
df_tm_pxb['营销场景'] = '品销宝'
|
2753
|
-
|
2754
2647
|
# 因为 2024.04.16及之前的营销场景报表不含超级直播,所以在此添加
|
2755
2648
|
if start_date < pd.to_datetime('2024-04-17'):
|
2756
2649
|
projection = {
|
@@ -2788,7 +2681,7 @@ class MysqlDatasQuery:
|
|
2788
2681
|
'成交金额': ('总成交金额', np.max)
|
2789
2682
|
}
|
2790
2683
|
)
|
2791
|
-
|
2684
|
+
# 京东数据
|
2792
2685
|
projection = {
|
2793
2686
|
'日期': 1,
|
2794
2687
|
'产品线': 1,
|
@@ -2832,7 +2725,6 @@ class MysqlDatasQuery:
|
|
2832
2725
|
df_jd = df_jd[['日期', '店铺名称', '产品线', '花费', '展现数', '点击数', '加购量', '成交笔数', '成交金额']]
|
2833
2726
|
df_jd.rename(columns={'产品线': '营销场景', '展现数': '展现量', '点击数': '点击量'}, inplace=True)
|
2834
2727
|
df_jd = df_jd[df_jd['花费'] > 0]
|
2835
|
-
|
2836
2728
|
projection = {
|
2837
2729
|
'日期': 1,
|
2838
2730
|
'产品线': 1,
|
@@ -2867,7 +2759,7 @@ class MysqlDatasQuery:
|
|
2867
2759
|
df_jd_qzyx.rename(columns={'产品线': '营销场景'}, inplace=True)
|
2868
2760
|
df_jd_qzyx = df_jd_qzyx[['日期', '店铺名称', '营销场景', '花费', '展现量', '点击量', '成交笔数', '成交金额']]
|
2869
2761
|
df_jd_qzyx = df_jd_qzyx[df_jd_qzyx['花费'] > 0]
|
2870
|
-
|
2762
|
+
# 京东自营店数据
|
2871
2763
|
projection = {
|
2872
2764
|
'日期': 1,
|
2873
2765
|
'产品线': 1,
|
@@ -3045,7 +2937,6 @@ class MysqlDatasQuery:
|
|
3045
2937
|
)
|
3046
2938
|
idx = df.groupby(['日期', '店铺名称', 'spuid'])['更新时间'].idxmax()
|
3047
2939
|
df = df.loc[idx]
|
3048
|
-
|
3049
2940
|
# 调整列顺序, 定义需要前置的列
|
3050
2941
|
cols_to_move = ['日期','平台','店铺名称','品牌名','商品名称', '商品款号','spuid', '一级类目名称', '二级类目名称', '三级类目名称']
|
3051
2942
|
# 生成新的列顺序:前置列 + 剩余列(保持原顺序)
|
@@ -3146,7 +3037,6 @@ class MysqlDatasQuery:
|
|
3146
3037
|
'消费能力等级': 1,
|
3147
3038
|
'用户性别': 1,
|
3148
3039
|
}
|
3149
|
-
# projection = {}
|
3150
3040
|
df_crowd = self.download_manager.data_to_df(
|
3151
3041
|
db_name='达摩盘3',
|
3152
3042
|
table_name='我的人群属性',
|
@@ -3158,7 +3048,6 @@ class MysqlDatasQuery:
|
|
3158
3048
|
df_crowd.drop_duplicates(subset=['人群id',], keep='last', inplace=True, ignore_index=True)
|
3159
3049
|
df_crowd.pop('日期')
|
3160
3050
|
df_crowd = df_crowd.astype({'人群id': 'int64'}, errors='ignore')
|
3161
|
-
|
3162
3051
|
projection = {}
|
3163
3052
|
__res = []
|
3164
3053
|
for year in range(2024, datetime.datetime.today().year + 1):
|
@@ -3178,8 +3067,6 @@ class MysqlDatasQuery:
|
|
3178
3067
|
# 清除一些不必要的字符
|
3179
3068
|
df['用户年龄'] = df['用户年龄'].apply(lambda x: '~'.join(re.findall(r'^(\d+).*-(\d+)岁$', str(x))[0]) if '岁' in str(x) else x)
|
3180
3069
|
df['消费能力等级'] = df['消费能力等级'].apply(lambda x: f'L{''.join(re.findall(r'(\d)', str(x)))}' if '购买力' in str(x) else x)
|
3181
|
-
# df.to_csv('/Users/xigua/Downloads/test3.csv', index=False, header=True, encoding='utf-8_sig')
|
3182
|
-
# breakpoint()
|
3183
3070
|
df.rename(columns={'消耗_元': '消耗'}, inplace=True)
|
3184
3071
|
set_typ = {
|
3185
3072
|
'日期': 'date',
|
@@ -3416,7 +3303,6 @@ class MysqlDatasQuery:
|
|
3416
3303
|
result_i = re.findall('_i$|_i_|^i_', str(keyword), re.IGNORECASE)
|
3417
3304
|
result_p = re.findall('_p$|_p_|_pl|^p_||^pl_', str(keyword), re.IGNORECASE)
|
3418
3305
|
result_l = re.findall('_l$|_l_|^l_', str(keyword), re.IGNORECASE)
|
3419
|
-
|
3420
3306
|
datas = [
|
3421
3307
|
{
|
3422
3308
|
'类别': 'A',
|
@@ -3435,7 +3321,6 @@ class MysqlDatasQuery:
|
|
3435
3321
|
'值': result_l,
|
3436
3322
|
}
|
3437
3323
|
]
|
3438
|
-
|
3439
3324
|
is_res = False
|
3440
3325
|
for data in datas:
|
3441
3326
|
if data['值']:
|
@@ -3568,7 +3453,6 @@ class MysqlDatasQuery:
|
|
3568
3453
|
'成交金额': ('成交金额', np.sum)
|
3569
3454
|
}
|
3570
3455
|
)
|
3571
|
-
|
3572
3456
|
zb.rename(columns={
|
3573
3457
|
'观看次数': '点击量',
|
3574
3458
|
}, inplace=True)
|
@@ -3596,16 +3480,13 @@ class MysqlDatasQuery:
|
|
3596
3480
|
'直接成交金额': 'float64',
|
3597
3481
|
'自然流量曝光量': 'int64',
|
3598
3482
|
}, errors='raise')
|
3599
|
-
|
3600
3483
|
df = pd.concat([tg, zb, pxb], axis=0, ignore_index=True)
|
3601
3484
|
df.fillna(0, inplace=True) # concat 之后要填充空值
|
3602
|
-
df = df.astype(
|
3603
|
-
|
3604
|
-
|
3605
|
-
|
3606
|
-
|
3607
|
-
)
|
3608
|
-
[df[col].apply(lambda x: '0' if str(x) == '' else x) for col in df.columns.tolist()]
|
3485
|
+
df = df.astype({
|
3486
|
+
'商品id': str,
|
3487
|
+
'自然流量曝光量': 'int64',
|
3488
|
+
})
|
3489
|
+
df.replace(to_replace='', value=0, inplace=True)
|
3609
3490
|
set_typ = {
|
3610
3491
|
'日期': 'date',
|
3611
3492
|
'店铺名称': 'varchar(100)',
|
@@ -3650,7 +3531,6 @@ def get_day_of_month(num):
|
|
3650
3531
|
_, _lastDay = calendar.monthrange(months_ago.year, months_ago.month) # 返回月的第一天的星期和当月总天数
|
3651
3532
|
_firstDay = datetime.date(months_ago.year, months_ago.month, day=1).strftime('%Y-%m-%d')
|
3652
3533
|
_lastDay = datetime.date(months_ago.year, months_ago.month, day=_lastDay).strftime('%Y-%m-%d')
|
3653
|
-
|
3654
3534
|
return _firstDay, _lastDay
|
3655
3535
|
|
3656
3536
|
|
@@ -3690,9 +3570,7 @@ def date_table():
|
|
3690
3570
|
group['第n周_new'] = f'第{num}周'
|
3691
3571
|
num += 1
|
3692
3572
|
__res.append(group.copy())
|
3693
|
-
# break
|
3694
3573
|
df = pd.concat(__res, ignore_index=True)
|
3695
|
-
# df['日期'] = df['日期'].apply(lambda x: pd.to_datetime(x))
|
3696
3574
|
df['weekname'] = df['日期'].dt.day_name()
|
3697
3575
|
dict_dt = {
|
3698
3576
|
'Monday': '星期一',
|
@@ -3746,7 +3624,6 @@ def date_table():
|
|
3746
3624
|
def query1(months=1, download_manager=None):
|
3747
3625
|
sdq = MysqlDatasQuery(download_manager=download_manager) # 实例化数据处理类
|
3748
3626
|
sdq.months = months # 设置数据周期, 1 表示近 2 个月
|
3749
|
-
|
3750
3627
|
# 依赖表 -- >>
|
3751
3628
|
sdq.tg_wxt(db_name='聚合数据', table_name='天猫_主体报表')
|
3752
3629
|
sdq.tg_cjzb(db_name='聚合数据', table_name='天猫_超级直播')
|
@@ -3792,7 +3669,6 @@ def query3(months=1, download_manager=None):
|
|
3792
3669
|
def main(months=3):
|
3793
3670
|
# 1. 更新日期表 更新货品年份基准表, 属性设置 3 - 货品年份基准
|
3794
3671
|
date_table()
|
3795
|
-
|
3796
3672
|
# 2. 数据聚合
|
3797
3673
|
download_manager = s_query.QueryDatas(
|
3798
3674
|
username=username,
|
@@ -3808,5 +3684,4 @@ def main(months=3):
|
|
3808
3684
|
|
3809
3685
|
if __name__ == '__main__':
|
3810
3686
|
# main(months=3)
|
3811
|
-
|
3812
3687
|
pass
|
@@ -321,14 +321,14 @@ def main():
|
|
321
321
|
# "sku榜单": [['日期', '平台', '店铺名称', '条码']],
|
322
322
|
# "spu榜单": [['日期', '平台', '店铺名称', '商品款号', '访客量']],
|
323
323
|
# },
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
324
|
+
"生意参谋3": {
|
325
|
+
# "crm成交客户": [['客户id']],
|
326
|
+
# "商品排行": [['日期', '店铺名称', '商品id']],
|
327
|
+
"流量来源构成": [['日期', '店铺名称', '来源构成', '类别', '一级来源', '二级来源', '三级来源']],
|
328
|
+
# "手淘搜索": [['日期', '店铺名称', '搜索词', '词类型', '访客数']],
|
329
|
+
# "新品追踪": [['日期', '店铺名称', '商品id']],
|
330
|
+
# "直播分场次效果": [['场次id']],
|
331
|
+
},
|
332
332
|
# "生意经3": {
|
333
333
|
# "sku销量_按名称": [['日期', '店铺名称', '宝贝id', 'sku名称', '销售额']],
|
334
334
|
# "sku销量_按商家编码": [['日期', '店铺名称', '宝贝id', 'sku编码', '销售额']],
|
@@ -46,7 +46,7 @@ def count_decimal_places(num_str: str) -> Tuple[int, int]:
|
|
46
46
|
|
47
47
|
|
48
48
|
class StatementCache(dict):
|
49
|
-
"""
|
49
|
+
"""LRU缓存实现,用于SQL语句缓存"""
|
50
50
|
def __init__(self, maxsize=100):
|
51
51
|
super().__init__()
|
52
52
|
self._maxsize = maxsize
|
@@ -71,10 +71,10 @@ class StatementCache(dict):
|
|
71
71
|
|
72
72
|
class MySQLUploader:
|
73
73
|
"""
|
74
|
-
MySQL
|
74
|
+
MySQL数据上传
|
75
75
|
|
76
|
-
|
77
|
-
|
76
|
+
用于将数据上传到MySQL数据库,支持自动建表、分表、数据验证等功能。
|
77
|
+
使用连接池管理数据库连接。
|
78
78
|
"""
|
79
79
|
def __init__(
|
80
80
|
self,
|
@@ -128,9 +128,7 @@ class MySQLUploader:
|
|
128
128
|
self._max_cached_statements = 100 # 用于控制 StatementCache 类中缓存的 SQL 语句数量,最多缓存 100 条 SQL 语句
|
129
129
|
self._table_metadata_cache = {}
|
130
130
|
self.metadata_cache_ttl = 300 # 5分钟缓存时间
|
131
|
-
|
132
|
-
# 创建连接池
|
133
|
-
self.pool = self._create_connection_pool()
|
131
|
+
self.pool = self._create_connection_pool() # 创建连接池
|
134
132
|
|
135
133
|
def _create_connection_pool(self) -> PooledDB:
|
136
134
|
"""
|
@@ -584,6 +582,8 @@ class MySQLUploader:
|
|
584
582
|
elif 'varchar' in column_type_lower:
|
585
583
|
if isinstance(value, str):
|
586
584
|
return value.replace('\\', '\\\\').replace("'", "\\'")
|
585
|
+
else:
|
586
|
+
return str(value)
|
587
587
|
elif 'text' in column_type_lower:
|
588
588
|
if isinstance(value, str):
|
589
589
|
max_length = 65535
|
@@ -592,7 +592,9 @@ class MySQLUploader:
|
|
592
592
|
'库': db_name, '表': table_name, '列': col_name, '原始值': f'{value[:50]}...', '截断后值': f'{value[:50]}...'
|
593
593
|
})
|
594
594
|
value = value[:max_length]
|
595
|
-
|
595
|
+
return value.replace('\\', '\\\\').replace("'", "\\'")
|
596
|
+
else:
|
597
|
+
return str(value)
|
596
598
|
elif 'json' in column_type_lower:
|
597
599
|
return json.dumps(value) if value is not None else None
|
598
600
|
else:
|
@@ -1200,6 +1202,9 @@ class MySQLUploader:
|
|
1200
1202
|
'失败': total_failed
|
1201
1203
|
})
|
1202
1204
|
|
1205
|
+
# 更新索引
|
1206
|
+
self._update_indexes(db_name, table_name, indexes)
|
1207
|
+
|
1203
1208
|
@_execute_with_retry
|
1204
1209
|
def _insert_data(
|
1205
1210
|
self,
|
@@ -1492,25 +1497,6 @@ class MySQLUploader:
|
|
1492
1497
|
logger.error('单行插入失败', {'库': db_name, '表': table_name, '错误': str(e)})
|
1493
1498
|
return total_inserted, total_skipped, total_failed
|
1494
1499
|
|
1495
|
-
def close(self) -> None:
|
1496
|
-
"""
|
1497
|
-
关闭连接池并清理资源
|
1498
|
-
这个方法会安全地关闭数据库连接池,并清理相关资源。
|
1499
|
-
建议结束时手动调用此方法。
|
1500
|
-
:raises: 可能抛出关闭连接时的异常
|
1501
|
-
"""
|
1502
|
-
try:
|
1503
|
-
if hasattr(self, 'pool') and self.pool is not None:
|
1504
|
-
try:
|
1505
|
-
# self.pool.close() # PooledDB 没有 close 方法
|
1506
|
-
self.pool = None
|
1507
|
-
except Exception as e:
|
1508
|
-
logger.warning('关闭连接池时出错', {'error': str(e)})
|
1509
|
-
logger.debug('finished', {'uploader.py': '连接池关闭'})
|
1510
|
-
except Exception as e:
|
1511
|
-
logger.error('关闭连接池失败', {'uploader.py': str(e)})
|
1512
|
-
raise
|
1513
|
-
|
1514
1500
|
def _check_pool_health(self) -> bool:
|
1515
1501
|
"""
|
1516
1502
|
检查连接池健康状态,防止连接泄露
|
@@ -1583,12 +1569,6 @@ class MySQLUploader:
|
|
1583
1569
|
# pandas DataFrame
|
1584
1570
|
return f"DataFrame shape={obj.shape}, head={obj.head(1).to_dict()}"
|
1585
1571
|
return obj
|
1586
|
-
|
1587
|
-
def __enter__(self):
|
1588
|
-
return self
|
1589
|
-
|
1590
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
1591
|
-
self.close()
|
1592
1572
|
|
1593
1573
|
def _normalize_col(self, col: str) -> str:
|
1594
1574
|
"""
|
@@ -1597,6 +1577,112 @@ class MySQLUploader:
|
|
1597
1577
|
safe = self._validate_identifier(col)
|
1598
1578
|
return safe if self.case_sensitive else safe.lower()
|
1599
1579
|
|
1580
|
+
def _update_indexes(self, db_name: str, table_name: str, indexes: Optional[List[str]]):
|
1581
|
+
"""
|
1582
|
+
更新索引,避免重复添加或更新,同时注意大小写一致性。
|
1583
|
+
|
1584
|
+
:param db_name: 数据库名
|
1585
|
+
:param table_name: 表名
|
1586
|
+
:param indexes: 需要更新的索引列列表
|
1587
|
+
"""
|
1588
|
+
if not indexes:
|
1589
|
+
return
|
1590
|
+
|
1591
|
+
# 规范化索引列名
|
1592
|
+
normalized_indexes = [self._normalize_col(idx) for idx in indexes]
|
1593
|
+
|
1594
|
+
# 获取现有索引
|
1595
|
+
try:
|
1596
|
+
existing_indexes = self._get_existing_indexes(db_name, table_name)
|
1597
|
+
except Exception as e:
|
1598
|
+
logger.error('获取现有索引时发生错误', {'库': db_name, '表': table_name, '错误': str(e)})
|
1599
|
+
raise
|
1600
|
+
|
1601
|
+
# 获取表中现有的列名
|
1602
|
+
try:
|
1603
|
+
existing_columns = self._get_existing_indexes(db_name, table_name)
|
1604
|
+
except Exception as e:
|
1605
|
+
logger.error('获取现有列时发生错误', {'库': db_name, '表': table_name, '错误': str(e)})
|
1606
|
+
raise
|
1607
|
+
|
1608
|
+
# 找出需要添加的索引
|
1609
|
+
indexes_to_add = [idx for idx in normalized_indexes if idx not in existing_indexes and idx in existing_columns]
|
1610
|
+
|
1611
|
+
# 添加新索引
|
1612
|
+
for idx in indexes_to_add:
|
1613
|
+
try:
|
1614
|
+
self._add_index(db_name, table_name, idx)
|
1615
|
+
except Exception as e:
|
1616
|
+
logger.error('添加索引时发生错误', {'库': db_name, '表': table_name, '列': idx, '错误': str(e)})
|
1617
|
+
raise
|
1618
|
+
|
1619
|
+
def _get_existing_indexes(self, db_name: str, table_name: str) -> Set[str]:
|
1620
|
+
"""
|
1621
|
+
获取表中现有的索引列名。
|
1622
|
+
|
1623
|
+
:param db_name: 数据库名
|
1624
|
+
:param table_name: 表名
|
1625
|
+
:return: 现有索引列名的集合
|
1626
|
+
"""
|
1627
|
+
sql = """
|
1628
|
+
SELECT COLUMN_NAME
|
1629
|
+
FROM INFORMATION_SCHEMA.STATISTICS
|
1630
|
+
WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s
|
1631
|
+
"""
|
1632
|
+
existing_indexes = set()
|
1633
|
+
try:
|
1634
|
+
with self._get_connection() as conn:
|
1635
|
+
with conn.cursor() as cursor:
|
1636
|
+
cursor.execute(sql, (db_name, table_name))
|
1637
|
+
existing_indexes = {row['COLUMN_NAME'] for row in cursor.fetchall()}
|
1638
|
+
except Exception as e:
|
1639
|
+
logger.error('获取现有索引失败', {'库': db_name, '表': table_name, '错误': str(e)})
|
1640
|
+
raise
|
1641
|
+
return existing_indexes
|
1642
|
+
|
1643
|
+
def _add_index(self, db_name: str, table_name: str, column: str):
|
1644
|
+
"""
|
1645
|
+
添加索引到指定列。
|
1646
|
+
|
1647
|
+
:param db_name: 数据库名
|
1648
|
+
:param table_name: 表名
|
1649
|
+
:param column: 需要添加索引的列名
|
1650
|
+
"""
|
1651
|
+
sql = f'ALTER TABLE `{db_name}`.`{table_name}` ADD INDEX `idx_{column}` (`{column}`)'
|
1652
|
+
try:
|
1653
|
+
with self._get_connection() as conn:
|
1654
|
+
with conn.cursor() as cursor:
|
1655
|
+
cursor.execute(sql)
|
1656
|
+
conn.commit()
|
1657
|
+
logger.debug('已为列创建索引', {'库': db_name, '表': table_name, '列': column})
|
1658
|
+
except Exception as e:
|
1659
|
+
logger.error('创建索引失败', {'库': db_name, '表': table_name, '列': column, '错误': str(e)})
|
1660
|
+
raise
|
1661
|
+
|
1662
|
+
def __enter__(self):
|
1663
|
+
return self
|
1664
|
+
|
1665
|
+
def close(self) -> None:
|
1666
|
+
"""
|
1667
|
+
关闭连接池并清理资源
|
1668
|
+
这个方法会安全地关闭数据库连接池,并清理相关资源。
|
1669
|
+
建议结束时手动调用此方法。
|
1670
|
+
:raises: 可能抛出关闭连接时的异常
|
1671
|
+
"""
|
1672
|
+
try:
|
1673
|
+
if hasattr(self, 'pool') and self.pool is not None:
|
1674
|
+
try:
|
1675
|
+
self.pool = None
|
1676
|
+
except Exception as e:
|
1677
|
+
logger.warning('关闭连接池时出错', {'error': str(e)})
|
1678
|
+
logger.debug('finished', {'uploader.py': '连接池关闭'})
|
1679
|
+
except Exception as e:
|
1680
|
+
logger.error('关闭连接池失败', {'uploader.py': str(e)})
|
1681
|
+
raise
|
1682
|
+
|
1683
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
1684
|
+
self.close()
|
1685
|
+
|
1600
1686
|
|
1601
1687
|
def main():
|
1602
1688
|
dir_path = os.path.expanduser("~")
|
mdbq-4.0.5/mdbq/__version__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
VERSION = '4.0.5'
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|