import_parameters.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. """
  2. 参数数据导入脚本
  3. @description: 从Excel文件读取Parameters参数数据并导入到Parameters表
  4. """
  5. import os
  6. import sys
  7. import pandas as pd
  8. import logging
  9. from datetime import datetime
  10. # 添加项目根目录到Python路径
  11. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  12. from app.database import engine, SessionLocal
  13. from app.models.parameters import Parameters # 确保你已创建Parameters模型
  14. # 设置日志
  15. logging.basicConfig(
  16. level=logging.INFO,
  17. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  18. )
  19. logger = logging.getLogger(__name__)
  20. class ParametersDataImporter:
  21. """
  22. 参数数据导入器
  23. @description: 从Excel文件读取参数数据并导入到Parameters表
  24. """
  25. def __init__(self, excel_path, sheet_name='Parameters'):
  26. """
  27. 初始化导入器
  28. @param {str} excel_path - Excel文件路径
  29. @param {str} sheet_name - Sheet名称,默认为'Parameters'
  30. """
  31. self.excel_path = excel_path
  32. self.sheet_name = sheet_name
  33. # 定义参数列的默认值映射
  34. self.default_values = {
  35. 'F1': 0.6,
  36. 'F2': 0.85,
  37. 'F3': 0.05,
  38. 'F4': 0.158,
  39. 'F5': 0.06,
  40. 'F6': 0.065,
  41. 'F7': 0.6,
  42. 'F8': 0.25,
  43. 'F9': 0.35,
  44. 'F10': 0.25,
  45. 'F11': 800,
  46. 'NF': 0.05,
  47. 'PF': 0.158,
  48. 'KF': 0.06,
  49. 'CF': 0.065,
  50. 'OF': 0.6,
  51. 'P': 0.25,
  52. 'FF': 0.35,
  53. 'AF': 0.25,
  54. 'Area': '韶关'
  55. }
  56. # 定义必需的最小参数列
  57. self.required_columns = ['Area']
  58. def read_excel_data(self):
  59. """
  60. 读取Excel文件数据
  61. @returns: DataFrame 读取的数据
  62. """
  63. try:
  64. logger.info(f"开始读取Excel文件: {self.excel_path}")
  65. logger.info(f"Sheet名称: {self.sheet_name}")
  66. # 检查文件是否存在
  67. if not os.path.exists(self.excel_path):
  68. raise FileNotFoundError(f"Excel文件不存在: {self.excel_path}")
  69. # 读取Excel文件
  70. df = pd.read_excel(self.excel_path, sheet_name=self.sheet_name)
  71. logger.info(f"成功读取数据,共 {len(df)} 行")
  72. logger.info(f"数据列: {list(df.columns)}")
  73. # 显示前几行数据供确认
  74. logger.info("前5行数据预览:")
  75. logger.info(df.head().to_string())
  76. return df
  77. except Exception as e:
  78. logger.error(f"读取Excel文件失败: {str(e)}")
  79. raise
  80. def validate_data(self, df):
  81. """
  82. 验证数据格式和完整性
  83. @param {DataFrame} df - 要验证的数据
  84. @returns: DataFrame 验证后的数据
  85. """
  86. try:
  87. logger.info("开始验证数据...")
  88. # 检查必需的列是否存在
  89. missing_columns = [col for col in self.required_columns if col not in df.columns]
  90. if missing_columns:
  91. raise ValueError(f"缺少必需的列: {missing_columns}")
  92. # 确保数据文件包含所有参数列
  93. for column in self.default_values.keys():
  94. if column not in df.columns:
  95. logger.warning(f"列 {column} 不存在于Excel文件中,将使用默认值 {self.default_values[column]}")
  96. df[column] = self.default_values[column]
  97. # 验证数值列的数据类型
  98. numeric_columns = list(self.default_values.keys())
  99. numeric_columns.remove('Area') # Area不是数值类型
  100. for col in numeric_columns:
  101. # 尝试转换为数值类型
  102. df[col] = pd.to_numeric(df[col], errors='coerce')
  103. # 检查是否有无效值
  104. if df[col].isnull().any():
  105. invalid_rows = df[df[col].isnull()]
  106. logger.warning(f"列 {col} 中有无效值,行号: {list(invalid_rows.index)}")
  107. # 填充默认值
  108. logger.info(f"将为无效行填充默认值 {self.default_values[col]}")
  109. df[col] = df[col].fillna(self.default_values[col])
  110. # 确保Area列是字符串类型
  111. if 'Area' in df.columns:
  112. df['Area'] = df['Area'].astype(str)
  113. logger.info(f"数据验证完成,有效数据 {len(df)} 行")
  114. return df
  115. except Exception as e:
  116. logger.error(f"数据验证失败: {str(e)}")
  117. raise
  118. def import_data(self, df):
  119. """
  120. 将数据导入到数据库
  121. @param {DataFrame} df - 要导入的数据
  122. """
  123. try:
  124. logger.info("开始导入数据到数据库...")
  125. # 创建数据库会话
  126. db = SessionLocal()
  127. try:
  128. # 检查是否有重复数据
  129. existing_count = db.query(Parameters).count()
  130. logger.info(f"数据库中现有参数记录: {existing_count} 条")
  131. # 如果已有数据,先删除现有数据
  132. if existing_count > 0:
  133. db.query(Parameters).delete()
  134. logger.info(f"已删除 {existing_count} 条现有参数记录")
  135. # 获取总行数
  136. total_rows = len(df)
  137. imported_count = 0
  138. skipped_count = 0
  139. # 使用ORM模型创建对象并插入
  140. for i, row in df.iterrows():
  141. try:
  142. # 创建参数对象
  143. param = Parameters(
  144. f1=row['F1'],
  145. f2=row['F2'],
  146. f3=row['F3'],
  147. f4=row['F4'],
  148. f5=row['F5'],
  149. f6=row['F6'],
  150. f7=row['F7'],
  151. f8=row['F8'],
  152. f9=row['F9'],
  153. f10=row['F10'],
  154. f11=row['F11'],
  155. nf=row['NF'],
  156. pf=row['PF'],
  157. kf=row['KF'],
  158. cf=row['CF'],
  159. of=row['OF'],
  160. p=row['P'],
  161. ff=row['FF'],
  162. af=row['AF'],
  163. area=row['Area']
  164. )
  165. # 添加到会话
  166. db.add(param)
  167. imported_count += 1
  168. # 每100条提交一次
  169. if imported_count % 100 == 0:
  170. db.commit()
  171. logger.info(f"已导入 {imported_count}/{total_rows} 条数据")
  172. except Exception as e:
  173. logger.warning(f"跳过行 {i}: {str(e)}")
  174. skipped_count += 1
  175. db.rollback() # 回滚当前会话
  176. # 提交剩余的数据
  177. db.commit()
  178. logger.info(f"参数导入完成! 成功导入 {imported_count} 条数据, 跳过 {skipped_count} 条无效数据")
  179. # 验证导入结果
  180. final_count = db.query(Parameters).count()
  181. logger.info(f"导入后数据库参数记录: {final_count} 条")
  182. except Exception as e:
  183. db.rollback()
  184. logger.error(f"数据导入失败,已回滚: {str(e)}")
  185. raise
  186. finally:
  187. db.close()
  188. except Exception as e:
  189. logger.error(f"数据导入过程失败: {str(e)}")
  190. raise
  191. def run_import(self):
  192. """
  193. 执行完整的导入流程
  194. """
  195. try:
  196. logger.info("=" * 60)
  197. logger.info("开始参数数据导入流程")
  198. logger.info("=" * 60)
  199. # 1. 读取Excel数据
  200. df = self.read_excel_data()
  201. # 2. 验证数据
  202. df = self.validate_data(df)
  203. # 3. 导入数据
  204. self.import_data(df)
  205. logger.info("=" * 60)
  206. logger.info("参数数据导入流程完成!")
  207. logger.info("=" * 60)
  208. except Exception as e:
  209. logger.error(f"导入流程失败: {str(e)}")
  210. raise
  211. def main():
  212. """
  213. 主函数
  214. """
  215. # Excel文件路径
  216. excel_path = r"D:\destkop\数据库对应数据.xlsx" # 或你的文件路径
  217. sheet_name = "Parameters" # 确保你的Excel文件中有这个sheet
  218. try:
  219. # 创建导入器并执行导入
  220. importer = ParametersDataImporter(excel_path, sheet_name)
  221. importer.run_import()
  222. except Exception as e:
  223. logger.error(f"程序执行失败: {str(e)}")
  224. sys.exit(1)
  225. if __name__ == "__main__":
  226. main()