mdbq 3.9.13__tar.gz → 3.9.14__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.
Files changed (36) hide show
  1. {mdbq-3.9.13 → mdbq-3.9.14}/PKG-INFO +1 -1
  2. mdbq-3.9.14/mdbq/__version__.py +1 -0
  3. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/log/mylogger.py +1 -1
  4. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/mysql/uploader.py +57 -84
  5. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq.egg-info/PKG-INFO +1 -1
  6. mdbq-3.9.13/mdbq/__version__.py +0 -1
  7. {mdbq-3.9.13 → mdbq-3.9.14}/README.txt +0 -0
  8. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/__init__.py +0 -0
  9. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/aggregation/__init__.py +0 -0
  10. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/aggregation/optimize.py +0 -0
  11. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/aggregation/query_data.py +0 -0
  12. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/config/__init__.py +0 -0
  13. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/config/config.py +0 -0
  14. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/log/__init__.py +0 -0
  15. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/log/spider_logging.py +0 -0
  16. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/mysql/__init__.py +0 -0
  17. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/mysql/deduplicator.py +0 -0
  18. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/mysql/mysql.py +0 -0
  19. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/mysql/s_query.py +0 -0
  20. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/other/__init__.py +0 -0
  21. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/other/download_sku_picture.py +0 -0
  22. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/other/otk.py +0 -0
  23. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/other/pov_city.py +0 -0
  24. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/other/ua_sj.py +0 -0
  25. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/pbix/__init__.py +0 -0
  26. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/pbix/pbix_refresh.py +0 -0
  27. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/pbix/refresh_all.py +0 -0
  28. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/redis/__init__.py +0 -0
  29. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/redis/getredis.py +0 -0
  30. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/spider/__init__.py +0 -0
  31. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq/spider/aikucun.py +0 -0
  32. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq.egg-info/SOURCES.txt +0 -0
  33. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq.egg-info/dependency_links.txt +0 -0
  34. {mdbq-3.9.13 → mdbq-3.9.14}/mdbq.egg-info/top_level.txt +0 -0
  35. {mdbq-3.9.13 → mdbq-3.9.14}/setup.cfg +0 -0
  36. {mdbq-3.9.13 → mdbq-3.9.14}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mdbq
3
- Version: 3.9.13
3
+ Version: 3.9.14
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -0,0 +1 @@
1
+ VERSION = '3.9.14'
@@ -222,7 +222,7 @@ class MyLogger:
222
222
  'timestamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
223
223
  'level': record.levelname,
224
224
  'message': record.getMessage(),
225
- 'name': record.name,
225
+ # 'name': record.name,
226
226
  # 'module': record.module,
227
227
  # 'function': record.funcName,
228
228
  }
@@ -138,7 +138,6 @@ class MySQLUploader:
138
138
  if hasattr(self, 'pool') and self.pool is not None and self._check_pool_health():
139
139
  return self.pool
140
140
 
141
- start_time = time.time()
142
141
  self.pool = None
143
142
 
144
143
  pool_params = {
@@ -172,18 +171,14 @@ class MySQLUploader:
172
171
 
173
172
  try:
174
173
  pool = PooledDB(**pool_params)
175
- elapsed = round(time.time() - start_time, 2)
176
174
  logger.info("连接池创建成功", {
177
- 'pool_size': self.pool_size,
178
- '耗时': elapsed
175
+ '连接池': self.pool_size
179
176
  })
180
177
  return pool
181
178
  except Exception as e:
182
- elapsed = round(time.time() - start_time, 2)
183
179
  self.pool = None
184
180
  logger.error("连接池创建失败", {
185
- 'error': str(e),
186
- '耗时': elapsed
181
+ 'error': str(e)
187
182
  })
188
183
  raise ConnectionError(f"连接池创建失败: {str(e)}")
189
184
 
@@ -198,7 +193,6 @@ class MySQLUploader:
198
193
  @wraps(func)
199
194
  def wrapper(*args, **kwargs):
200
195
  last_exception = None
201
- start_time = time.time()
202
196
  operation = func.__name__
203
197
 
204
198
  logger.debug(f"开始执行操作: {operation}", {
@@ -209,18 +203,15 @@ class MySQLUploader:
209
203
  for attempt in range(self.max_retries):
210
204
  try:
211
205
  result = func(*args, **kwargs)
212
- elapsed = round(time.time() - start_time, 2)
213
206
 
214
207
  if attempt > 0:
215
208
  logger.info("操作成功(重试后)", {
216
209
  'operation': operation,
217
- 'attempts': attempt + 1,
218
- '耗时': elapsed
210
+ 'attempts': attempt + 1
219
211
  })
220
212
  else:
221
213
  logger.debug("操作成功", {
222
- 'operation': operation,
223
- '耗时': elapsed
214
+ 'operation': operation
224
215
  })
225
216
 
226
217
  return result
@@ -252,15 +243,11 @@ class MySQLUploader:
252
243
  'error': str(reconnect_error)
253
244
  })
254
245
  else:
255
- elapsed = round(time.time() - start_time, 2)
256
- error_details['耗时'] = elapsed
257
- logger.error(f"操作最终失败 {error_details}")
246
+ logger.error(f"操作最终失败")
258
247
 
259
248
  except pymysql.IntegrityError as e:
260
- elapsed = round(time.time() - start_time, 2)
261
249
  logger.error("完整性约束错误", {
262
250
  'operation': operation,
263
- '耗时': elapsed,
264
251
  'error_code': e.args[0] if e.args else None,
265
252
  'error_message': e.args[1] if len(e.args) > 1 else None
266
253
  })
@@ -268,10 +255,8 @@ class MySQLUploader:
268
255
 
269
256
  except Exception as e:
270
257
  last_exception = e
271
- elapsed = round(time.time() - start_time, 2)
272
258
  logger.error("发生意外错误", {
273
259
  'operation': operation,
274
- '耗时': elapsed,
275
260
  'error_type': type(e).__name__,
276
261
  'error_message': str(e),
277
262
  'error_args': e.args if hasattr(e, 'args') else None
@@ -334,9 +319,9 @@ class MySQLUploader:
334
319
  with conn.cursor() as cursor:
335
320
  cursor.execute(sql)
336
321
  conn.commit()
337
- logger.info(f"{db_name} 数据库已创建")
322
+ logger.info(f"`{db_name}` 数据库已创建")
338
323
  except Exception as e:
339
- logger.error(f"{db_name}: 无法创建数据库 {str(e)}")
324
+ logger.error(f"无法创建数据库: `{db_name}` -> {str(e)}")
340
325
  conn.rollback()
341
326
  raise
342
327
 
@@ -354,22 +339,10 @@ class MySQLUploader:
354
339
  # date_obj = datetime.datetime.strptime(date_value, '%Y-%m-%d')
355
340
  date_obj = self._validate_datetime(date_value, True)
356
341
  except ValueError:
357
- error_msg = f"`{table_name}` 无效的日期格式1: {date_value}"
342
+ error_msg = f"`{table_name}` 无效的日期格式1: `{date_value}`"
358
343
  logger.error(error_msg)
359
344
  raise ValueError(error_msg)
360
345
 
361
- # try:
362
- # # date_obj = datetime.datetime.strptime(date_value, '%Y-%m-%d %H:%M:%S')
363
- # date_obj = self._validate_datetime(date_value, True)
364
- # except ValueError:
365
- # try:
366
- # # date_obj = datetime.datetime.strptime(date_value, '%Y-%m-%d')
367
- # date_obj = self._validate_datetime(date_value, True)
368
- # except ValueError:
369
- # error_msg = f"无效的日期格式1: {date_value}"
370
- # logger.error(error_msg)
371
- # raise ValueError(error_msg)
372
-
373
346
  if partition_by == 'year':
374
347
  return f"{table_name}_{date_obj.year}"
375
348
  elif partition_by == 'month':
@@ -388,7 +361,7 @@ class MySQLUploader:
388
361
  :raises ValueError: 当标识符无效时抛出
389
362
  """
390
363
  if not identifier or not isinstance(identifier, str):
391
- error_msg = f"无效的标识符: {identifier}"
364
+ error_msg = f"无效的标识符: `{identifier}`"
392
365
  logger.error(error_msg)
393
366
  raise ValueError(error_msg)
394
367
 
@@ -399,7 +372,7 @@ class MySQLUploader:
399
372
  cleaned = re.sub(r'_+', '_', cleaned).strip('_')
400
373
 
401
374
  if not cleaned:
402
- error_msg = f"无法清理异常标识符: {identifier}"
375
+ error_msg = f"无法清理异常标识符: `{identifier}`"
403
376
  logger.error(error_msg)
404
377
  raise ValueError(error_msg)
405
378
 
@@ -409,7 +382,7 @@ class MySQLUploader:
409
382
  'not', 'like', 'in', 'is', 'null', 'true', 'false', 'between'
410
383
  }
411
384
  if cleaned.lower() in mysql_keywords:
412
- logger.debug(f"存在MySQL保留字: {cleaned}")
385
+ logger.debug(f"存在MySQL保留字: `{cleaned}`")
413
386
  return f"`{cleaned}`"
414
387
 
415
388
  return cleaned
@@ -522,7 +495,7 @@ class MySQLUploader:
522
495
  with self._get_connection() as conn:
523
496
  with conn.cursor() as cursor:
524
497
  cursor.execute(sql)
525
- logger.info(f"{db_name}.{table_name}: 数据表已创建")
498
+ logger.info(f"`{db_name}`.`{table_name}`: 数据表已创建")
526
499
 
527
500
  # 添加普通索引
528
501
  index_statements = []
@@ -551,10 +524,10 @@ class MySQLUploader:
551
524
  logger.debug(f"Executed index statement: {stmt}", )
552
525
 
553
526
  conn.commit()
554
- logger.info(f"{db_name}.{table_name}: 索引已添加")
527
+ logger.info(f"索引已添加: `{db_name}`.`{table_name}` -> `{indexes}`")
555
528
 
556
529
  except Exception as e:
557
- logger.error(f"{db_name}.{table_name}: 建表失败: {str(e)}")
530
+ logger.error(f"`{db_name}`.`{table_name}`: 建表失败: {str(e)}")
558
531
  conn.rollback()
559
532
  raise
560
533
 
@@ -587,7 +560,7 @@ class MySQLUploader:
587
560
  return datetime.datetime.strptime(value, fmt).strftime('%Y-%m-%d %H:%M:%S')
588
561
  except ValueError:
589
562
  continue
590
- raise ValueError(f"无效的日期格式2: {value}")
563
+ raise ValueError(f"无效的日期格式2: `{value}`")
591
564
 
592
565
  def _validate_value(self, value: Any, column_type: str, allow_null: bool) -> Any:
593
566
  """
@@ -625,7 +598,7 @@ class MySQLUploader:
625
598
  try:
626
599
  return int(float(value))
627
600
  except ValueError:
628
- raise ValueError(f"`{value}` 无法转为整数")
601
+ raise ValueError(f"`{value}` -> 无法转为整数")
629
602
  return int(value) if value is not None else None
630
603
  elif any(t in column_type_lower for t in ['float', 'double', 'decimal']):
631
604
  if isinstance(value, str):
@@ -639,7 +612,7 @@ class MySQLUploader:
639
612
  try:
640
613
  return self._validate_datetime(value) # 使用专门的日期验证方法
641
614
  except ValueError as e:
642
- raise ValueError(f"无效日期格式: {value} - {str(e)}")
615
+ raise ValueError(f"无效日期格式: `{value}` -> {str(e)}")
643
616
  return str(value)
644
617
  elif 'char' in column_type_lower or 'text' in column_type_lower:
645
618
  # 防止SQL注入
@@ -678,7 +651,7 @@ class MySQLUploader:
678
651
  with conn.cursor() as cursor:
679
652
  cursor.execute(sql, (db_name, table_name))
680
653
  set_typ = {row['COLUMN_NAME']: row['DATA_TYPE'] for row in cursor.fetchall()}
681
- logger.debug(f"{db_name}.{table_name}: 获取表的列信息: {set_typ}")
654
+ logger.debug(f"`{db_name}`.`{table_name}`: 获取表的列信息: `{set_typ}`")
682
655
  return set_typ
683
656
  except Exception as e:
684
657
  logger.error(f"无法获取表列信息: {str(e)}")
@@ -707,21 +680,21 @@ class MySQLUploader:
707
680
  self._create_table(db_name, table_name, set_typ, primary_keys, date_column, indexes,
708
681
  allow_null=allow_null)
709
682
  else:
710
- error_msg = f"数据表不存在: '{db_name}.{table_name}'"
683
+ error_msg = f"数据表不存在: `{db_name}`.`{table_name}`"
711
684
  logger.error(error_msg)
712
685
  raise ValueError(error_msg)
713
686
 
714
687
  # 获取表结构并验证
715
688
  table_columns = self._get_table_columns(db_name, table_name)
716
689
  if not table_columns:
717
- error_msg = f"获取列失败 '{db_name}.{table_name}'"
690
+ error_msg = f"获取列失败 `{db_name}`.`{table_name}`"
718
691
  logger.error(error_msg)
719
692
  raise ValueError(error_msg)
720
693
 
721
694
  # 验证数据列与表列匹配
722
695
  for col in set_typ:
723
696
  if col not in table_columns:
724
- error_msg = f"列不存在: '{col}' -> '{db_name}.{table_name}'"
697
+ error_msg = f"列不存在: `{col}` -> `{db_name}`.`{table_name}`"
725
698
  logger.error(error_msg)
726
699
  raise ValueError(error_msg)
727
700
 
@@ -869,7 +842,7 @@ class MySQLUploader:
869
842
  if sample_values:
870
843
  inferred_type = self._infer_data_type(sample_values[0])
871
844
  filtered_set_typ[col] = inferred_type
872
- logger.debug(f"自动推断列 `{col}` 的数据类型为: {inferred_type}")
845
+ logger.debug(f"自动推断列 `{col}` 的数据类型为: `{inferred_type}`")
873
846
  else:
874
847
  # 没有样本值,使用默认类型
875
848
  filtered_set_typ[col] = 'VARCHAR(255)'
@@ -941,13 +914,13 @@ class MySQLUploader:
941
914
  batch_id = f"batch_{int(time.time() * 1000)}"
942
915
  success_flag = False
943
916
 
944
- logger.info("开始上传数据", {
945
- '批次号': batch_id,
917
+ logger.info("开始上传", {
946
918
  '库': db_name,
947
919
  '表': table_name,
920
+ '批次': batch_id,
948
921
  '分表方式': partition_by,
949
922
  '排重': check_duplicate,
950
- '总计行数': len(data) if hasattr(data, '__len__') else 1,
923
+ '传入总计': len(data) if hasattr(data, '__len__') else 1,
951
924
  '自动建表': auto_create
952
925
  })
953
926
 
@@ -959,7 +932,7 @@ class MySQLUploader:
959
932
  if partition_by:
960
933
  partition_by = str(partition_by).lower()
961
934
  if partition_by not in ['year', 'month']:
962
- error_msg = "分表方式必须是 'year' 或 'month'"
935
+ error_msg = "分表方式必须是 'year' 或 'month' 或 'None'"
963
936
  logger.error(error_msg)
964
937
  raise ValueError(error_msg)
965
938
 
@@ -971,7 +944,7 @@ class MySQLUploader:
971
944
  if auto_create:
972
945
  self._create_database(db_name)
973
946
  else:
974
- error_msg = f"数据库不存在: '{db_name}'"
947
+ error_msg = f"数据库不存在: `{db_name}`"
975
948
  logger.error(error_msg)
976
949
  raise ValueError(error_msg)
977
950
 
@@ -981,8 +954,12 @@ class MySQLUploader:
981
954
  for row in prepared_data:
982
955
  try:
983
956
  if partition_date_column not in row:
984
- error_msg = f"异常缺失列 '{partition_date_column}'"
985
- logger.error(error_msg)
957
+ logger.error('缺失列',{
958
+ '库': db_name,
959
+ '表': table_name,
960
+ '批次': batch_id,
961
+ '异常缺失列': partition_date_column,
962
+ })
986
963
  continue # 跳过当前行
987
964
 
988
965
  part_table = self._get_partition_table_name(
@@ -1011,7 +988,7 @@ class MySQLUploader:
1011
988
  )
1012
989
  except Exception as e:
1013
990
  logger.error("分表上传失败", {
1014
- 'partition_table': part_table,
991
+ '分表': part_table,
1015
992
  'error': str(e)
1016
993
  })
1017
994
  continue # 跳过当前分表,继续处理其他分表
@@ -1027,16 +1004,17 @@ class MySQLUploader:
1027
1004
  success_flag = True
1028
1005
 
1029
1006
  except Exception as e:
1030
- logger.error("上传过程中发生全局错误", {
1007
+ logger.error("上传过程发生全局错误", {
1031
1008
  'error': str(e),
1032
1009
  'error_type': type(e).__name__
1033
1010
  })
1034
1011
  finally:
1035
- elapsed = round(time.time() - upload_start, 2)
1036
1012
  logger.info("上传处理完成", {
1037
- '批次号': batch_id,
1013
+ '': db_name,
1014
+ '表': table_name,
1015
+ '批次': batch_id,
1038
1016
  'success': success_flag,
1039
- '耗时': elapsed,
1017
+ '耗时': round(time.time() - upload_start, 2),
1040
1018
  '数据行': initial_row_count
1041
1019
  })
1042
1020
 
@@ -1158,17 +1136,16 @@ class MySQLUploader:
1158
1136
  total_failed += 1
1159
1137
 
1160
1138
  # 记录失败行详细信息
1161
- error_details = {
1162
- '批次号': batch_id,
1139
+ logger.error(f"单行插入失败", {
1163
1140
  '库': db_name,
1164
1141
  '表': table_name,
1142
+ '批次': batch_id,
1165
1143
  'error_type': type(e).__name__,
1166
1144
  'error_message': str(e),
1167
1145
  '数据类型': set_typ,
1168
1146
  '是否排重': check_duplicate,
1169
1147
  '排重列': duplicate_columns
1170
- }
1171
- logger.error(f"单行插入失败: {error_details}")
1148
+ })
1172
1149
  continue # 跳过当前行,继续处理下一行
1173
1150
 
1174
1151
  # 更新统计信息
@@ -1181,8 +1158,10 @@ class MySQLUploader:
1181
1158
  total_inserted += successful_rows
1182
1159
 
1183
1160
  batch_elapsed = round(time.time() - batch_start, 2)
1184
- batch_info = {
1185
- '批次号': batch_id,
1161
+ logger.debug("批次处理完成", {
1162
+ '': db_name,
1163
+ '表': table_name,
1164
+ '批次': batch_id,
1186
1165
  'batch_index': i // batch_size + 1,
1187
1166
  'total_batches': (len(data) + batch_size - 1) // batch_size,
1188
1167
  'batch_size': len(batch),
@@ -1190,14 +1169,15 @@ class MySQLUploader:
1190
1169
  'failed_rows': len(batch) - successful_rows,
1191
1170
  '耗时': batch_elapsed,
1192
1171
  'rows_per_second': successful_rows / batch_elapsed if batch_elapsed > 0 else 0
1193
- }
1194
- logger.debug(f"批次处理完成 {batch_info}")
1172
+ })
1195
1173
 
1196
- logger.info("数据插入完成", {
1197
- '总数据行': len(data),
1198
- '插入行数': total_inserted,
1199
- '跳过行数': total_skipped,
1200
- '失败行数': total_failed
1174
+ logger.info('插入完成', {
1175
+ '': db_name,
1176
+ '': table_name,
1177
+ '完成总计': len(data),
1178
+ '插入': total_inserted,
1179
+ '跳过': total_skipped,
1180
+ '失败': total_failed
1201
1181
  })
1202
1182
 
1203
1183
  def close(self):
@@ -1205,8 +1185,6 @@ class MySQLUploader:
1205
1185
  关闭连接池并清理资源
1206
1186
  :raises: 可能抛出关闭连接时的异常
1207
1187
  """
1208
- close_start = time.time()
1209
-
1210
1188
  try:
1211
1189
  if hasattr(self, 'pool') and self.pool is not None:
1212
1190
  # 更安全的关闭方式
@@ -1219,15 +1197,10 @@ class MySQLUploader:
1219
1197
 
1220
1198
  self.pool = None
1221
1199
 
1222
- elapsed = round(time.time() - close_start, 2)
1223
- logger.info("连接池已关闭", {
1224
- '耗时': elapsed
1225
- })
1200
+ logger.info("连接池已关闭")
1226
1201
  except Exception as e:
1227
- elapsed = round(time.time() - close_start, 2)
1228
1202
  logger.error("关闭连接池失败", {
1229
- 'error': str(e),
1230
- '耗时': elapsed
1203
+ 'error': str(e)
1231
1204
  })
1232
1205
  raise
1233
1206
 
@@ -1261,7 +1234,7 @@ class MySQLUploader:
1261
1234
  if attempt < max_retries - 1:
1262
1235
  time.sleep(delay * (attempt + 1))
1263
1236
  continue
1264
- raise logger.error(f"操作重试{max_retries}次后失败")
1237
+ raise logger.error(f"操作重试 {max_retries} 次后失败")
1265
1238
  except Exception as e:
1266
1239
  raise logger.error(f"操作失败: {str(e)}")
1267
1240
  raise last_exception if last_exception else logger.error("操作重试失败,未知错误")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mdbq
3
- Version: 3.9.13
3
+ Version: 3.9.14
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -1 +0,0 @@
1
- VERSION = '3.9.13'
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