WaveTrans.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import json
  2. import multiprocessing
  3. import traceback
  4. from conf.constants import ParallelProcessing
  5. from etl.common.WaveData import WaveData
  6. from service.plt_service import get_all_wind
  7. from service.trans_conf_service import update_trans_status_running, update_trans_transfer_progress, \
  8. update_trans_status_success, update_trans_status_error
  9. from service.trans_service import get_wave_conf, save_df_to_db, get_or_create_wave_table, \
  10. get_wave_data, delete_exist_wave_data
  11. from utils.file.trans_methods import *
  12. from utils.log.trans_log import set_trance_id, info, error
  13. from utils.systeminfo.sysinfo import get_available_cpu_count_with_percent
  14. # env = "qianan"
  15. # if len(sys.argv) >= 2:
  16. # env = sys.argv[1]
  17. #
  18. # if env.endswith(".yaml"):
  19. # conf_path = env
  20. # else:
  21. # conf_path = os.path.abspath(f"C:/project/energy-data-trans/conf/etl_config_{env}.yaml")
  22. #
  23. # os.environ["ETL_CONF"] = conf_path
  24. # yaml_config = yaml_conf(conf_path)
  25. # os.environ["env"] = env
  26. exec("import datetime")
  27. exec("from os.path import *")
  28. exec("import re")
  29. class WaveTrans(object):
  30. """波形数据转换类"""
  31. def __init__(self, id: int, wind_farm_code: str, wind_farm_name: str, read_dir: str):
  32. """
  33. 初始化波形数据转换类
  34. Args:
  35. id: 任务ID
  36. wind_farm_code: 风电场编码
  37. read_dir: 读取目录
  38. """
  39. self.id = id
  40. self.wind_farm_code = wind_farm_code
  41. self.wind_farm_name = wind_farm_name
  42. self.read_dir = read_dir
  43. self.begin = datetime.datetime.now()
  44. self.engine_count = 0
  45. self.min_date = None
  46. self.max_date = None
  47. self.data_count = 0
  48. def get_data_exec(self, func_code: str, filepath: str, measupoint_names: List[str]) -> List[WaveData]:
  49. exec(func_code)
  50. return locals()['get_data'](filepath, measupoint_names) or []
  51. # return self.get_data(filepath, measupoint_names)
  52. def del_exists_data(self, df: pd.DataFrame):
  53. """
  54. 删除已存在的数据
  55. Args:
  56. df: 数据帧
  57. """
  58. min_date, max_date = df['time_stamp'].min(), df['time_stamp'].max()
  59. if self.min_date is None:
  60. self.min_date = min_date
  61. if self.max_date is None:
  62. self.max_date = max_date
  63. self.min_date = min(self.min_date, min_date)
  64. self.max_date = max(self.max_date, max_date)
  65. db_df = get_wave_data(self.wind_farm_code + '_wave', min_date, max_date)
  66. db_df['type'] = db_df['type'].astype(str)
  67. df['type'] = df['type'].astype(str)
  68. db_df['time_stamp'] = pd.to_datetime(db_df['time_stamp'], errors='coerce')
  69. df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
  70. exists_df = pd.merge(db_df, df,
  71. on=['detection_type', 'end_frequency', 'eu_spectrum', 'mesure_point_name',
  72. 'sampling_frequency', 'samples', 'start_frequency', 'time_stamp', 'type',
  73. 'wind_turbine_name', 'window_type'],
  74. how='inner')
  75. ids = [int(i) for i in exists_df['id'].to_list()]
  76. if ids:
  77. delete_exist_wave_data(self.wind_farm_code + "_wave", ids)
  78. def run(self):
  79. """运行波形数据转换"""
  80. update_trans_status_running(self.id)
  81. trance_id = '-'.join([self.wind_farm_code, 'wave'])
  82. set_trance_id(trance_id)
  83. wave_conf = get_wave_conf(self.wind_farm_code)
  84. filter_types = wave_conf.get("filter_types", "txt,csv")
  85. filter_types = filter_types.replace(",", ",")
  86. all_files = read_files(self.read_dir, [str(i).strip() for i in filter_types.split(",")])
  87. wind_turbine_name_set = set()
  88. if len(all_files) > 0:
  89. update_trans_transfer_progress(self.id, 5)
  90. # 最大取系统cpu的 1/2
  91. split_count = get_available_cpu_count_with_percent(1 / 2)
  92. # 限制最大进程数
  93. split_count = min(split_count, ParallelProcessing.MAX_PROCESSES)
  94. all_wind, _ = get_all_wind(self.wind_farm_code, False)
  95. # all_wind = {}
  96. get_or_create_wave_table(self.wind_farm_code + '_wave', self.wind_farm_name)
  97. base_param_exec = wave_conf.get('base_param_exec', '')
  98. map_dict = {}
  99. if base_param_exec:
  100. base_param_exec = base_param_exec.replace('\r\n', '\n').replace('\t', ' ')
  101. info(base_param_exec)
  102. if 'import ' in base_param_exec:
  103. raise Exception("方法不支持import方法")
  104. mesure_poins = [key for key, value in wave_conf.items() if str(key).startswith('conf_') and value]
  105. for point in mesure_poins:
  106. point_names = wave_conf[point].strip().split('|')
  107. for name in point_names:
  108. map_dict[name] = point.replace('conf_', '')
  109. # 优化批次大小
  110. batch_size = split_count * 10
  111. all_array = split_array(all_files, batch_size)
  112. total_index = len(all_array)
  113. for index, now_array in enumerate(all_array):
  114. index_begin = datetime.datetime.now()
  115. with multiprocessing.Pool(split_count,maxtasksperchild=5) as pool:
  116. try:
  117. file_datas_result = pool.starmap(self.get_data_exec,
  118. [(base_param_exec, i, list(map_dict.keys())) for i in
  119. now_array])
  120. file_datas = [x for sub in file_datas_result if sub for x in sub if x]
  121. info(f'总数:{len(now_array)},返回个数{len(file_datas)}')
  122. except Exception as e:
  123. message = str(e)
  124. error(traceback.format_exc())
  125. update_trans_status_error(self.id, message[0:len(message) if len(message) < 100 else 100])
  126. raise e
  127. update_trans_transfer_progress(self.id, 20 + int(index / total_index * 60))
  128. info("读取文件耗时:", datetime.datetime.now() - self.begin)
  129. result_list = [vars(i) for i in file_datas if i]
  130. if result_list:
  131. self.data_count += len(result_list)
  132. df = pd.DataFrame(result_list)
  133. df['time_stamp'] = df['time_stamp'].apply(lambda x: x.split('.')[0])
  134. # df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
  135. # df['time_stamp'] = df['time_stamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
  136. df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
  137. df['mesure_point_name'] = df['mesure_point_name'].map(map_dict)
  138. df.dropna(subset=['mesure_point_name'], inplace=True)
  139. df['wind_turbine_number'] = df['wind_turbine_name'].map(all_wind).fillna(df['wind_turbine_name'])
  140. # 批量处理JSON序列化
  141. df['mesure_data_time'] = df['mesure_data_time'].apply(lambda x: json.dumps(x))
  142. df['mesure_data_frenquency'] = df['mesure_data_frenquency'].apply(lambda x: json.dumps(x))
  143. df['mesure_data_env'] = df['mesure_data_env'].apply(lambda x: json.dumps(x))
  144. df.sort_values(by=['time_stamp', 'mesure_point_name'], inplace=True)
  145. for col in df['wind_turbine_name'].unique():
  146. wind_turbine_name_set.add(col)
  147. self.del_exists_data(df)
  148. save_df_to_db(self.wind_farm_code + '_wave', df, batch_count=40)
  149. info(f"总共{total_index}组,当前{index + 1}", "本次写入耗时:", datetime.datetime.now() - index_begin,
  150. "总耗时:", datetime.datetime.now() - self.begin)
  151. update_trans_status_success(self.id, len(wind_turbine_name_set), None,
  152. self.min_date, self.max_date, self.data_count)
  153. info("总耗时:", datetime.datetime.now() - self.begin)
  154. # if __name__ == '__main__':
  155. # trans = WaveTrans(1, 'WOF043800107', '乾安风电场', r'C:\迅雷云盘\04-01\A28')
  156. #
  157. # trans.run()