mdbq 4.1.1__py3-none-any.whl → 4.1.3__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 mdbq might be problematic. Click here for more details.

mdbq/__version__.py CHANGED
@@ -1 +1 @@
1
- VERSION = '4.1.1'
1
+ VERSION = '4.1.3'
mdbq/myconf/myconf.py CHANGED
@@ -1,22 +1,22 @@
1
1
  import re
2
2
  from typing import Dict, Any, Optional, Union, List, Tuple, Type, TypeVar
3
3
  from pathlib import Path
4
- from mdbq.log import mylogger
4
+ # from mdbq.log import mylogger
5
5
  from dataclasses import dataclass, field
6
6
  from enum import Enum
7
7
  import time
8
8
 
9
- logger = mylogger.MyLogger(
10
- logging_mode='both',
11
- log_level='info',
12
- log_format='json',
13
- max_log_size=50,
14
- backup_count=5,
15
- enable_async=False, # 是否启用异步日志
16
- sample_rate=1, # 采样DEBUG/INFO日志
17
- sensitive_fields=[], # 敏感字段过滤
18
- enable_metrics=False, # 是否启用性能指标
19
- )
9
+ # logger = mylogger.MyLogger(
10
+ # logging_mode='both',
11
+ # log_level='info',
12
+ # log_format='json',
13
+ # max_log_size=50,
14
+ # backup_count=5,
15
+ # enable_async=False, # 是否启用异步日志
16
+ # sample_rate=1, # 采样DEBUG/INFO日志
17
+ # sensitive_fields=[], # 敏感字段过滤
18
+ # enable_metrics=False, # 是否启用性能指标
19
+ # )
20
20
 
21
21
  T = TypeVar('T') # 类型变量
22
22
 
@@ -151,12 +151,10 @@ class ConfigParser:
151
151
  def open(self, file_path: Union[str, Path]) -> 'ConfigParser':
152
152
  """打开配置文件"""
153
153
  file_path = Path(file_path)
154
- logger.debug(f'尝试打开配置文件: {file_path}')
155
154
  if not file_path.exists() and not self.options.auto_create:
156
- logger.error(f'配置文件不存在: {file_path}')
155
+ # logger.error(f'配置文件不存在: {file_path}')
157
156
  raise ConfigException.file_not_found(file_path)
158
157
  self._current_file = file_path
159
- logger.debug(f'配置文件已打开: {file_path}')
160
158
  return self
161
159
 
162
160
  def _ensure_file_open(self) -> None:
@@ -211,7 +209,6 @@ class ConfigParser:
211
209
 
212
210
  def _update_cache(self, file_path: str, config: Dict[str, Any]) -> None:
213
211
  """更新配置缓存"""
214
- logger.debug(f'更新配置缓存: {file_path}')
215
212
  self._config_cache[file_path] = config
216
213
  self._cache_timestamps[file_path] = time.time()
217
214
 
@@ -236,13 +233,11 @@ class ConfigParser:
236
233
  def _clear_cache(self, file_path: Optional[str] = None) -> None:
237
234
  """清除配置缓存"""
238
235
  if file_path:
239
- logger.debug(f'清除指定文件的缓存: {file_path}')
240
236
  self._config_cache.pop(file_path, None)
241
237
  self._cache_timestamps.pop(file_path, None)
242
238
  self._comments_cache.pop(file_path, None)
243
239
  self._section_map.pop(file_path, None)
244
240
  else:
245
- logger.debug('清除所有配置缓存')
246
241
  self._config_cache.clear()
247
242
  self._cache_timestamps.clear()
248
243
  self._comments_cache.clear()
@@ -323,12 +318,11 @@ class ConfigParser:
323
318
  default: Any = None, value_type: Optional[Type[T]] = None,
324
319
  file_path: Optional[Union[str, Path]] = None) -> T:
325
320
  """获取指定配置项的值"""
326
- logger.debug(f'获取配置项: section={section}, key={key}, file_path={file_path}')
327
321
  if file_path is None:
328
322
  self._ensure_file_open()
329
323
  file_path = self._current_file
330
324
  if not self._validate_key(key):
331
- logger.error(f'无效的键名: {key}')
325
+ # logger.error(f'无效的键名: {key}')
332
326
  raise ConfigException.invalid_key_error(key, file_path, section)
333
327
  config = self.read(file_path)
334
328
  section = section or self.options.default_section
@@ -336,15 +330,15 @@ class ConfigParser:
336
330
  original_section = self._get_original_section(str(file_path), normalized_section)
337
331
  if original_section is None:
338
332
  if default is not None:
339
- logger.warning(f'节不存在,返回默认值: section={section}, key={key}, default={default}')
333
+ # logger.warning(f'节不存在,返回默认值: section={section}, key={key}, default={default}')
340
334
  return default
341
- logger.error(f'配置节不存在: {section}')
335
+ # logger.error(f'配置节不存在: {section}')
342
336
  raise ConfigException.section_not_found(file_path, section)
343
337
  if key not in config[original_section]:
344
338
  if default is not None:
345
- logger.warning(f'键不存在,返回默认值: section={section}, key={key}, default={default}')
339
+ # logger.warning(f'键不存在,返回默认值: section={section}, key={key}, default={default}')
346
340
  return default
347
- logger.error(f'配置键不存在: {key}')
341
+ # logger.error(f'配置键不存在: {key}')
348
342
  raise ConfigException.key_not_found(file_path, original_section, key)
349
343
  value = config[original_section][key]
350
344
  if value_type is not None:
@@ -356,7 +350,6 @@ class ConfigParser:
356
350
  value_types: Optional[Dict[str, Type]] = None,
357
351
  file_path: Optional[Union[str, Path]] = None) -> Dict[str, Any]:
358
352
  """批量获取多个配置项的值"""
359
- logger.debug(f'批量获取配置项: section={section}, keys={keys}, file_path={file_path}')
360
353
  if file_path is None:
361
354
  self._ensure_file_open()
362
355
  file_path = self._current_file
@@ -375,7 +368,7 @@ class ConfigParser:
375
368
  )
376
369
  result[key] = value
377
370
  except ConfigException as e:
378
- logger.error(f"读取配置项失败: section={section}, key={key}, error={e}")
371
+ # logger.error(f"读取配置项失败: section={section}, key={key}, error={e}")
379
372
  if key in defaults:
380
373
  result[key] = defaults[key]
381
374
  else:
@@ -388,7 +381,6 @@ class ConfigParser:
388
381
  value_types: Optional[Dict[str, Type]] = None,
389
382
  file_path: Optional[Union[str, Path]] = None) -> Tuple[Any, ...]:
390
383
  """获取指定节点下多个键的值元组"""
391
- logger.debug(f'获取节下多个键的值: section={section}, keys={keys}, file_path={file_path}')
392
384
  if file_path is None:
393
385
  self._ensure_file_open()
394
386
  file_path = self._current_file
@@ -407,7 +399,7 @@ class ConfigParser:
407
399
  )
408
400
  result.append(value)
409
401
  except ConfigException as e:
410
- logger.error(f"读取配置项失败: section={section}, key={key}, error={e}")
402
+ # logger.error(f"读取配置项失败: section={section}, key={key}, error={e}")
411
403
  if key in defaults:
412
404
  result.append(defaults[key])
413
405
  else:
@@ -419,7 +411,6 @@ class ConfigParser:
419
411
  value_type: Optional[Type] = None,
420
412
  file_path: Optional[Union[str, Path]] = None) -> None:
421
413
  """设置指定配置项的值"""
422
- logger.debug(f'准备写入配置项: section={section}, key={key}, value={value}, file_path={file_path}')
423
414
  if file_path is None:
424
415
  self._ensure_file_open()
425
416
  file_path = self._current_file
@@ -427,7 +418,7 @@ class ConfigParser:
427
418
  file_path = Path(file_path)
428
419
 
429
420
  if not self._validate_key(key):
430
- logger.error(f'无效的键名: {key}')
421
+ # logger.error(f'无效的键名: {key}')
431
422
  raise ConfigException.invalid_key_error(key, file_path, section)
432
423
 
433
424
  section = section or self.options.default_section
@@ -452,7 +443,7 @@ class ConfigParser:
452
443
  else:
453
444
  value = value_type(value)
454
445
  except (ValueError, TypeError) as e:
455
- logger.error(f'类型转换失败: value={value}, type={value_type}, error={e}')
446
+ # logger.error(f'类型转换失败: value={value}, type={value_type}, error={e}')
456
447
  raise ConfigException.conversion_error(value, value_type, file_path, section=section, key=key)
457
448
 
458
449
  if isinstance(value, bool):
@@ -509,21 +500,20 @@ class ConfigParser:
509
500
  file.write(f'{key}={value}\n')
510
501
 
511
502
  self._clear_cache(str(file_path))
512
- logger.info(f'配置项写入成功: section={section}, key={key}, value={value}, file_path={file_path}')
503
+ # logger.info(f'配置项写入成功: section={section}, key={key}, value={value}, file_path={file_path}')
513
504
 
514
505
  except Exception as e:
515
- logger.error(f'写入配置项失败: section={section}, key={key}, value={value}, file_path={file_path}, error={e}')
506
+ # logger.error(f'写入配置项失败: section={section}, key={key}, value={value}, file_path={file_path}, error={e}')
516
507
  raise ConfigException.write_error(file_path, e)
517
508
 
518
509
  def set_values(self, section: Optional[str] = None, values: Dict[str, Any] = None,
519
510
  value_types: Optional[Dict[str, Type]] = None,
520
511
  file_path: Optional[Union[str, Path]] = None) -> None:
521
512
  """批量设置多个配置项的值"""
522
- logger.debug(f'批量写入配置项: section={section}, keys={list(values.keys())}, file_path={file_path}')
523
513
  for key, value in values.items():
524
514
  value_type = value_types.get(key) if value_types else None
525
515
  self.set_value(section, key, value, value_type, file_path)
526
- logger.info(f'批量写入配置项完成: section={section}, file_path={file_path}')
516
+ # logger.info(f'批量写入配置项完成: section={section}, file_path={file_path}')
527
517
 
528
518
  def validate_config(self, section: Optional[str] = None, schema: Dict[str, Type] = None,
529
519
  file_path: Optional[Union[str, Path]] = None) -> bool:
@@ -560,17 +550,15 @@ class ConfigParser:
560
550
  else:
561
551
  file_path = Path(file_path)
562
552
 
563
- logger.debug(f'开始读取配置文件: {file_path}')
564
553
  cached_config = self._get_cached_config(str(file_path))
565
554
  if cached_config is not None:
566
- logger.debug(f'命中配置缓存: {file_path}')
567
555
  return cached_config
568
556
 
569
557
  if not file_path.exists():
570
558
  if not self.options.auto_create:
571
- logger.error(f'配置文件不存在: {file_path}')
559
+ # logger.error(f'配置文件不存在: {file_path}')
572
560
  raise ConfigException.file_not_found(file_path)
573
- logger.info(f'配置文件不存在,将创建: {file_path}')
561
+ # logger.info(f'配置文件不存在,将创建: {file_path}')
574
562
  file_path.parent.mkdir(parents=True, exist_ok=True)
575
563
  file_path.touch()
576
564
  return {}
@@ -592,7 +580,7 @@ class ConfigParser:
592
580
  if stripped_line.startswith('[') and stripped_line.endswith(']'):
593
581
  current_section = stripped_line[1:-1]
594
582
  if not self._validate_key(current_section):
595
- logger.error(f'无效的节名: {current_section}')
583
+ # logger.error(f'无效的节名: {current_section}')
596
584
  raise ConfigException.invalid_section_error(current_section, file_path)
597
585
  self._update_section_map(str(file_path), current_section)
598
586
  if current_section not in config:
@@ -606,7 +594,7 @@ class ConfigParser:
606
594
  if key_value:
607
595
  key, value = key_value
608
596
  if not self._validate_key(key):
609
- logger.error(f'无效的键名: {key}')
597
+ # logger.error(f'无效的键名: {key}')
610
598
  raise ConfigException.invalid_key_error(key, file_path, current_section)
611
599
  value, comment = self._extract_comment(value)
612
600
 
@@ -621,11 +609,10 @@ class ConfigParser:
621
609
  self._comments_cache.setdefault(str(file_path), {}).setdefault(current_section, []).append(comment)
622
610
 
623
611
  self._update_cache(str(file_path), config)
624
- logger.debug(f'配置文件读取成功: {file_path}')
625
612
  return config
626
613
 
627
614
  except Exception as e:
628
- logger.error(f'读取配置文件失败: {file_path}, error={e}')
615
+ # logger.error(f'读取配置文件失败: {file_path}, error={e}')
629
616
  raise ConfigException.read_error(file_path, e)
630
617
 
631
618
 
@@ -168,7 +168,7 @@ class MySQLDeduplicator:
168
168
  self._dedup_end_date = today.strftime("%Y-%m-%d")
169
169
 
170
170
  if self._dedup_start_date and self._dedup_end_date:
171
- logger.info('去重日期范围', {'开始': self._dedup_start_date, '结束': self._dedup_end_date})
171
+ logger.debug('去重日期范围', {'开始': self._dedup_start_date, '结束': self._dedup_end_date})
172
172
 
173
173
  # 排除列处理,直接合并去重
174
174
  self.exclude_columns = list(set((exclude_columns or []) + ['id', '更新时间']))
@@ -515,7 +515,7 @@ class MySQLDeduplicator:
515
515
  dup_count_row = cursor.fetchone()
516
516
  dup_count = dup_count_row['cnt'] if dup_count_row and 'cnt' in dup_count_row else 0
517
517
  if dup_count == 0:
518
- logger.info('没有重复数据', {"库": database, "表": table, "数据量": total_count, "数据日期": date_val})
518
+ logger.debug('没有重复数据', {"库": database, "表": table, "数据量": total_count, "数据日期": date_val})
519
519
  cursor.execute(drop_temp_sql)
520
520
  conn.commit()
521
521
  return (0, 0)
@@ -626,7 +626,7 @@ class MySQLDeduplicator:
626
626
  dup_count_row = cursor.fetchone()
627
627
  dup_count = dup_count_row['cnt'] if dup_count_row and 'cnt' in dup_count_row else 0
628
628
  if dup_count == 0:
629
- logger.info('没有重复数据', {"库": database, "表": table, "数据量": total_count})
629
+ logger.debug('没有重复数据', {"库": database, "表": table, "数据量": total_count})
630
630
  cursor.execute(drop_temp_sql)
631
631
  conn.commit()
632
632
  return (0, 0)
@@ -722,7 +722,7 @@ class MySQLDeduplicator:
722
722
  if not self._check_table_exists(database, table):
723
723
  logger.warning('表不存在', {"库": database, "表": table, "warning": "跳过"})
724
724
  return (0, 0)
725
- logger.info('单表开始', {
725
+ logger.debug('单表开始', {
726
726
  "库": database,
727
727
  "表": table,
728
728
  # "参数": {
@@ -763,7 +763,7 @@ class MySQLDeduplicator:
763
763
  if start_date and end_date:
764
764
  all_dates = [d for d in all_dates if str(start_date) <= str(d) <= str(end_date)]
765
765
  if not all_dates:
766
- logger.info('无可处理日期', {"库": database, "表": table})
766
+ logger.debug('无可处理日期', {"库": database, "表": table})
767
767
  return (0, 0)
768
768
  total_dup = 0
769
769
  total_del = 0
@@ -794,7 +794,7 @@ class MySQLDeduplicator:
794
794
  logger.warning('分区处理失败', {"库": database, "表": table, "日期": date_val, "异常": err, "func": sys._getframe().f_code.co_name})
795
795
  total_dup += dup_count
796
796
  total_del += affected_rows
797
- logger.info('单表完成', {"库": database, "表": table, "结果[重复, 删除]": (total_dup, total_del), '日期范围': f"{start_date} - {end_date}", "唯一列": columns})
797
+ logger.debug('单表完成', {"库": database, "表": table, "结果[重复, 删除]": (total_dup, total_del), '日期范围': f"{start_date} - {end_date}", "唯一列": columns})
798
798
  # 自动重排id列(仅当有实际删除时且reorder_id为True)
799
799
  if reorder_id and total_del > 0:
800
800
  try:
@@ -858,7 +858,7 @@ class MySQLDeduplicator:
858
858
  if not target_tables:
859
859
  logger.info('数据库中没有表', {"库": database, "操作": "跳过"})
860
860
  return results
861
- logger.info('库统计', {"库": database, "表数量": len(target_tables), "表列表": target_tables})
861
+ logger.debug('库统计', {"库": database, "表数量": len(target_tables), "表列表": target_tables})
862
862
  if parallel and self.max_workers > 1:
863
863
  with concurrent.futures.ThreadPoolExecutor(
864
864
  max_workers=self.max_workers
@@ -1073,9 +1073,9 @@ class MySQLDeduplicator:
1073
1073
  if hasattr(self, 'pool') and self.pool and not self._closed:
1074
1074
  self.pool.close()
1075
1075
  self._closed = True
1076
- logger.info("数据库连接池已关闭")
1076
+ logger.debug("数据库连接池已关闭")
1077
1077
  else:
1078
- logger.info('连接池已关闭或不存在')
1078
+ logger.debug('连接池已关闭或不存在')
1079
1079
  except Exception as e:
1080
1080
  logger.error(f"关闭连接池时出错", {'error_type': type(e).__name__, 'error': str(e)})
1081
1081
 
@@ -1172,7 +1172,7 @@ class MySQLDeduplicator:
1172
1172
  with conn.cursor() as cursor:
1173
1173
  cursor.execute(f"SHOW CREATE TABLE {table_quoted}")
1174
1174
  create_table_sql = cursor.fetchone()['Create Table']
1175
- logger.info('开始id重排', {"库": database, "表": table, "重排列": id_column, "试运行": dry_run, "DDL警告": "MySQL DDL操作不可回滚,建议提前备份!"})
1175
+ logger.debug('开始id重排', {"库": database, "表": table, "重排列": id_column, "试运行": dry_run, "DDL警告": "MySQL DDL操作不可回滚,建议提前备份!"})
1176
1176
  if dry_run:
1177
1177
  logger.info('dry_run模式,打印原表结构', {"库": database, "表": table, "建表语句": create_table_sql})
1178
1178
  return True
@@ -1370,7 +1370,7 @@ def main():
1370
1370
  # recent_month=1,
1371
1371
  # date_range=['2025-06-09', '2025-06-10'],
1372
1372
  exclude_columns=['更新时间'],
1373
- exclude_databases=['cookie文件', '日志', '视频数据', '云电影', 'api_monitor_logs', 'redis统计', 'standalone_auth', 'website_data'],
1373
+ exclude_databases=['cookie文件', '日志', '视频数据', '云电影'],
1374
1374
  # exclude_tables={
1375
1375
  # '推广数据2': [
1376
1376
  # '地域报表_城市_2025_04',
mdbq/mysql/s_query.py CHANGED
@@ -16,7 +16,7 @@ from functools import wraps
16
16
  warnings.filterwarnings('ignore')
17
17
  logger = mylogger.MyLogger(
18
18
  logging_mode='file',
19
- log_level='info',
19
+ log_level='error',
20
20
  log_format='json',
21
21
  max_log_size=50,
22
22
  backup_count=5,
mdbq/mysql/uploader.py CHANGED
@@ -199,7 +199,7 @@ class MySQLUploader:
199
199
  try:
200
200
  result = func(self, *args, **kwargs)
201
201
  if attempt > 0:
202
- logger.info('操作成功(重试后)', {'operation': operation, 'attempts': attempt + 1})
202
+ logger.debug('操作成功(重试后)', {'operation': operation, 'attempts': attempt + 1})
203
203
  return result
204
204
  except (pymysql.OperationalError, pymysql.err.MySQLError) as e:
205
205
  last_exception = e
@@ -217,7 +217,7 @@ class MySQLUploader:
217
217
  time.sleep(wait_time)
218
218
  try:
219
219
  self.pool = self._create_connection_pool()
220
- logger.info('成功重新建立数据库连接')
220
+ logger.debug('成功重新建立数据库连接')
221
221
  except Exception as reconnect_error:
222
222
  logger.error('重连失败', {'error': str(reconnect_error)})
223
223
  else:
@@ -251,7 +251,7 @@ class MySQLUploader:
251
251
  try:
252
252
  self.pool = self._create_connection_pool()
253
253
  conn = self.pool.connection()
254
- logger.info('重建连接池后获取连接成功')
254
+ logger.debug('重建连接池后获取连接成功')
255
255
  return conn
256
256
  except Exception as e2:
257
257
  logger.error('重建连接池后依然获取连接失败', {'error': str(e2)})
@@ -296,7 +296,7 @@ class MySQLUploader:
296
296
  with conn.cursor() as cursor:
297
297
  cursor.execute(sql)
298
298
  conn.commit()
299
- logger.info('数据库已创建', {'库': db_name})
299
+ logger.debug('数据库已创建', {'库': db_name})
300
300
  except Exception as e:
301
301
  logger.error('无法创建数据库', {'库': db_name, '错误': str(e)})
302
302
  if conn is not None:
@@ -602,7 +602,7 @@ class MySQLUploader:
602
602
  with conn.cursor() as cursor:
603
603
  cursor.execute(sql)
604
604
  conn.commit()
605
- logger.info('数据表及索引已创建', {'库': db_name, '表': table_name, '索引': indexes, '唯一约束': unique_keys})
605
+ logger.debug('数据表及索引已创建', {'库': db_name, '表': table_name, '索引': indexes, '唯一约束': unique_keys})
606
606
  except Exception as e:
607
607
  logger.error('建表失败', {'库': db_name, '表': table_name, '错误': str(e), '异常类型': type(e).__name__})
608
608
  if conn is not None:
@@ -909,7 +909,7 @@ class MySQLUploader:
909
909
  return
910
910
  cursor.execute(sql_create)
911
911
  conn.commit()
912
- logger.info('已为列创建索引', {'库': db_name, '表': table_name, '列': column})
912
+ logger.debug('已为列创建索引', {'库': db_name, '表': table_name, '列': column})
913
913
  except Exception as e:
914
914
  logger.error('创建索引失败', {'库': db_name, '表': table_name, '列': column, '错误': str(e)})
915
915
  raise
@@ -953,7 +953,7 @@ class MySQLUploader:
953
953
  with conn.cursor() as cursor:
954
954
  cursor.execute(sql)
955
955
  conn.commit()
956
- logger.info('添加唯一约束列成功', {'库': db_name, '表': table_name, '列': unique_cols})
956
+ logger.debug('添加唯一约束列成功', {'库': db_name, '表': table_name, '列': unique_cols})
957
957
  except Exception as e:
958
958
  logger.warning('唯一约束列添加失败', {'库': db_name, '表': table_name, '列': unique_cols, '错误': str(e)})
959
959
 
@@ -1343,7 +1343,7 @@ class MySQLUploader:
1343
1343
  validated_indexes = self._validate_indexes_format(indexes, db_name, table_name)
1344
1344
  validated_unique_keys = self._validate_unique_keys_format(unique_keys, db_name, table_name)
1345
1345
 
1346
- logger.info("开始上传", {
1346
+ logger.debug("开始上传", {
1347
1347
  '库': db_name,
1348
1348
  '表': table_name,
1349
1349
  '批次': batch_id,
@@ -1548,7 +1548,7 @@ class MySQLUploader:
1548
1548
  batch_id, transaction_mode,
1549
1549
  update_on_duplicate
1550
1550
  )
1551
- logger.info('插入完成', {
1551
+ logger.debug('插入完成', {
1552
1552
  '库': db_name,
1553
1553
  '表': table_name,
1554
1554
  '总计': len(data),
mdbq/redis/getredis.py CHANGED
@@ -5,21 +5,21 @@ import numpy as np
5
5
  import json
6
6
  import datetime
7
7
  import threading
8
- from mdbq.log import mylogger
8
+ # from mdbq.log import mylogger
9
9
  from decimal import Decimal
10
10
  import orjson
11
11
 
12
- logger = mylogger.MyLogger(
13
- logging_mode='file',
14
- log_level='info',
15
- log_format='json',
16
- max_log_size=50,
17
- backup_count=5,
18
- enable_async=False, # 是否启用异步日志
19
- sample_rate=1, # 采样DEBUG/INFO日志
20
- sensitive_fields=[], # 敏感字段过滤
21
- enable_metrics=False, # 是否启用性能指标
22
- )
12
+ # logger = mylogger.MyLogger(
13
+ # logging_mode='file',
14
+ # log_level='info',
15
+ # log_format='json',
16
+ # max_log_size=50,
17
+ # backup_count=5,
18
+ # enable_async=False, # 是否启用异步日志
19
+ # sample_rate=1, # 采样DEBUG/INFO日志
20
+ # sensitive_fields=[], # 敏感字段过滤
21
+ # enable_metrics=False, # 是否启用性能指标
22
+ # )
23
23
 
24
24
 
25
25
  class RedisData(object):
@@ -61,7 +61,8 @@ class RedisData(object):
61
61
 
62
62
  combined_df = pd.concat(dfs, ignore_index=True) if dfs else pd.DataFrame()
63
63
  if combined_df.empty:
64
- logger.info(f"警告: {db_name}.{table_name} 未读取到数据")
64
+ # logger.info(f"警告: {db_name}.{table_name} 未读取到数据")
65
+ pass
65
66
  else:
66
67
  combined_df = self._convert_date_columns(combined_df)
67
68
  return combined_df
@@ -86,7 +87,7 @@ class RedisData(object):
86
87
  ttl = self.redis_engine.ttl(cache_key)
87
88
  cache_data = self._fetch_redis_data(cache_key)
88
89
  except Exception as e:
89
- logger.error(f"Redis 连接异常: {e},直接访问 MySQL")
90
+ # logger.error(f"Redis 连接异常: {e},直接访问 MySQL")
90
91
  return self.get_from_mysql(db_name, table_name, set_year, start_date, end_date)
91
92
 
92
93
  # 缓存失效处理逻辑
@@ -134,11 +135,11 @@ class RedisData(object):
134
135
  self.redis_engine.set(cache_key, serialized_data)
135
136
  self.redis_engine.expire(cache_key, self.cache_ttl)
136
137
 
137
- logger.info(f"缓存更新 {cache_key} | 数据量: {len(combined_data)}")
138
+ # logger.info(f"缓存更新 {cache_key} | 数据量: {len(combined_data)}")
138
139
  return combined_data
139
140
 
140
141
  except Exception as e:
141
- logger.error(f"缓存更新失败: {cache_key} - {str(e)}")
142
+ # logger.error(f"缓存更新失败: {cache_key} - {str(e)}")
142
143
  return pd.DataFrame()
143
144
 
144
145
  # Helper Methods ------------------------------------------------
@@ -160,7 +161,7 @@ class RedisData(object):
160
161
  projection={}
161
162
  )
162
163
  except Exception as e:
163
- logger.error(f"MySQL 查询异常 {db_name}.{table_name}: {e}")
164
+ # logger.error(f"MySQL 查询异常 {db_name}.{table_name}: {e}")
164
165
  return pd.DataFrame()
165
166
 
166
167
  def _fetch_redis_data(self, cache_key: str) -> pd.DataFrame:
@@ -173,7 +174,7 @@ class RedisData(object):
173
174
  df = pd.DataFrame(json.loads(data.decode("utf-8")))
174
175
  return self._convert_date_columns(df)
175
176
  except Exception as e:
176
- logger.error(f"Redis 数据解析失败 {cache_key}: {e}")
177
+ # logger.error(f"Redis 数据解析失败 {cache_key}: {e}")
177
178
  return pd.DataFrame()
178
179
 
179
180
  def _convert_date_columns(self, df: pd.DataFrame) -> pd.DataFrame:
@@ -278,7 +279,8 @@ class RedisDataHash(object):
278
279
 
279
280
  combined_df = pd.concat(dfs, ignore_index=True) if dfs else pd.DataFrame()
280
281
  if combined_df.empty:
281
- logger.warn(f"warning: {db_name}.{table_name} 未读取到数据")
282
+ # logger.warn(f"warning: {db_name}.{table_name} 未读取到数据")
283
+ pass
282
284
  else:
283
285
  combined_df = self._convert_date_columns(combined_df)
284
286
  return combined_df
@@ -293,7 +295,7 @@ class RedisDataHash(object):
293
295
  projection={}
294
296
  ) -> pd.DataFrame:
295
297
  if not self.redis_engine.ping():
296
- logger.error(f"Redis ping异常,直接访问 MySQL")
298
+ # logger.error(f"Redis ping异常,直接访问 MySQL")
297
299
  return self.get_from_mysql(db_name, table_name, set_year, start_date, end_date, projection)
298
300
  start_dt = pd.to_datetime(start_date).floor('D')
299
301
  end_dt = pd.to_datetime(end_date).floor('D')
@@ -335,7 +337,7 @@ class RedisDataHash(object):
335
337
  return self.get_from_mysql(db_name, table_name, set_year, start_date, end_date, projection)
336
338
 
337
339
  except Exception as e:
338
- logger.error(f"Redis 连接异常: {e},直接访问 MySQL")
340
+ # logger.error(f"Redis 连接异常: {e},直接访问 MySQL")
339
341
  return self.get_from_mysql(db_name, table_name, set_year, start_date, end_date, projection)
340
342
 
341
343
  def set_redis(
@@ -385,9 +387,10 @@ class RedisDataHash(object):
385
387
  serialized_data = self._serialize_data(group)
386
388
  self.redis_engine.hset(cache_key, month_str, serialized_data)
387
389
  self.redis_engine.expire(cache_key, self.cache_ttl + random.randint(0, 1800))
388
- logger.info(f"缓存更新 {cache_key} | 数据量: {len(combined_data)}")
390
+ # logger.info(f"缓存更新 {cache_key} | 数据量: {len(combined_data)}")
389
391
  except Exception as e:
390
- logger.error(f"缓存更新失败: {cache_key} - {str(e)}")
392
+ # logger.error(f"缓存更新失败: {cache_key} - {str(e)}")
393
+ pass
391
394
 
392
395
  def _fetch_table_data(
393
396
  self,
@@ -406,7 +409,7 @@ class RedisDataHash(object):
406
409
  projection=projection
407
410
  )
408
411
  except Exception as e:
409
- logger.error(f"MySQL 查询异常 {db_name}.{table_name}: {e}")
412
+ # logger.error(f"MySQL 查询异常 {db_name}.{table_name}: {e}")
410
413
  return pd.DataFrame()
411
414
 
412
415
  def _fetch_redis_data(self, cache_key: str, months: list = None) -> pd.DataFrame:
@@ -441,7 +444,8 @@ class RedisDataHash(object):
441
444
  df = self._convert_date_columns(df)
442
445
  dfs.append(df)
443
446
  except Exception as e:
444
- logger.error(f"月份数据解析失败 {field}: {e}")
447
+ # logger.error(f"月份数据解析失败 {field}: {e}")
448
+ pass
445
449
 
446
450
  # 处理分片数据(优化后的批处理逻辑)
447
451
  cursor, shard_data = results[result_index]
@@ -459,7 +463,8 @@ class RedisDataHash(object):
459
463
  df = pd.DataFrame(orjson.loads(value))
460
464
  dfs.append(self._convert_date_columns(df))
461
465
  except Exception as e:
462
- logger.error(f"分片数据解析失败: {e}")
466
+ # logger.error(f"分片数据解析失败: {e}")
467
+ pass
463
468
 
464
469
  # 继续获取后续分片
465
470
  if cursor == 0:
@@ -475,7 +480,7 @@ class RedisDataHash(object):
475
480
  return pd.DataFrame()
476
481
 
477
482
  except Exception as e:
478
- logger.error(f"Redis 数据获取失败 {cache_key}: {e}")
483
+ # logger.error(f"Redis 数据获取失败 {cache_key}: {e}")
479
484
  return pd.DataFrame()
480
485
 
481
486
  def _convert_date_columns(self, df: pd.DataFrame) -> pd.DataFrame:
@@ -562,7 +567,7 @@ class RedisDataHash(object):
562
567
  try:
563
568
  records = temp_df.to_dict(orient='records')
564
569
  except Exception as e:
565
- logger.error(f"DataFrame转字典失败: {str(e)}")
570
+ # logger.error(f"DataFrame转字典失败: {str(e)}")
566
571
  records = []
567
572
 
568
573
  # 序列化配置 --------------------------------------------------------