Day3_output_print()

        本来是不想记录print()这部分内容的,觉得也没啥东西,但这个课程有些新的点还蛮新奇的。我就把它记录下来了。
        功能:把输出内容存放到制定路径下的文档中
        代码<code>

# 将数据输出到指定文件中

file_name = open('D:/python_learn_by_self/python_full_stack/day2_print/test.py', 'a+')

print('output in this file', file=file_name)

        说实话,但看代码样子,真不要太简单好吧。但这里包含几个点。第一,open()函数的使用,在完全不知道路径下是否有目标文档的前提下,可以使用'a+'的方式确保一下。如果有就打开就好,如果没有就新建文档再打开。第二,print()函数,本身是有很多参数的,这里它使用的就是输出文件file这个参数,顾名思义就是把内容output到对应的文件中。
        结果

         这时候你有没有疑问?就是我可不可以直接把路径输入到print()函数中,不去open行不行?试试看,假设这个文件已经存在。
        代

为啥只连接不运行我的数据啊,我数据库第一次运行没数据阿,咋整 2025-07-31 08:47:01,432 - Colion.DatabaseManager - INFO - 已连接到数据库: d:\Programs\新框架\Colion_frame\Colion\data\colion.db (线程: Dummy-4) 2025-07-31 08:47:01,436 - Colion.model.output_plan - INFO - 从 daily_output_plan_final 获取到 0 条记录。 import os import sqlite3 from datetime import datetime import logging from pathlib import Path from Colion.model.database.db_manager import DatabaseManager # 修复导入问题 from Colion.core.path_helper import get_application_path, get_project_root logger = logging.getLogger(__name__) class OutputPlanModel: def __init__(self, db_manager: DatabaseManager = None): self.db_manager = db_manager if db_manager else DatabaseManager() self.sql_script_path = os.path.join(get_project_root(), &#39;process_daily_output.sql&#39;) self._ensure_final_table_exists() def _ensure_final_table_exists(self): """ 确保 daily_output_plan_final 表存在。 这个表结构需要与 process_daily_output.sql 中 INSERT INTO 的列保持一致。 """ create_table_sql = """ CREATE TABLE IF NOT EXISTS daily_output_plan_final ( "批次" TEXT, "指令" TEXT, "线体" TEXT, "单板代码" TEXT, "单板名称" TEXT, "计划数量" REAL, "产出数量" REAL, "剩余数量" REAL, "计划开始时间" TEXT, "计划结束时间" TEXT, "实际开始时间" TEXT, "修正后计划开始时间" TEXT, "修正后计划结束时间" TEXT, "主工序" TEXT, "工序序号" INTEGER, "入库工序" TEXT, "入库时间" TEXT, "产品大类" TEXT, "工厂" TEXT, "责任人" TEXT, "day_1_output" REAL, "day_2_output" REAL, "day_3_output" REAL, "day_4_output" REAL, "day_5_output" REAL, "day_6_output" REAL, "day_7_output" REAL ); """ try: self.db_manager.execute(create_table_sql) logger.info("daily_output_plan_final 表已存在或已成功创建。") except Exception as e: logger.error(f"创建 daily_output_plan_final 表失败: {e}") raise def process_and_save_daily_output_plan(self): """ 读取 SQL 脚本并执行,生成产出计划数据到 daily_output_plan_final 表。 """ if not os.path.exists(self.sql_script_path): logger.error(f"SQL 脚本文件未找到: {self.sql_script_path}") raise FileNotFoundError(f"SQL script not found at {self.sql_script_path}") try: with open(self.sql_script_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f: sql_script = f.read() logger.info(f"开始执行 SQL 脚本: {self.sql_script_path}") self.db_manager.execute_script(sql_script) logger.info("产出计划数据已成功生成并保存到 daily_output_plan_final 表。") return True except Exception as e: logger.error(f"执行 SQL 脚本失败: {e}", exc_info=True) return False def get_output_plan_data(self, filters: dict = None): """ 从 daily_output_plan_final 表获取产出计划数据。 """ query = "SELECT * FROM daily_output_plan_final WHERE 1=1" params = [] if filters: if &#39;factory&#39; in filters and filters[&#39;factory&#39;]: query += " AND 工厂 = ?" params.append(filters[&#39;factory&#39;]) if &#39;line&#39; in filters and filters[&#39;line&#39;]: query += " AND 线体 = ?" params.append(filters[&#39;line&#39;]) if &#39;item_no&#39; in filters and filters[&#39;item_no&#39;]: query += " AND 单板代码 LIKE ?" params.append(f"%{filters[&#39;item_no&#39;]}%") if &#39;start_date&#39; in filters and filters[&#39;start_date&#39;]: query += " AND 修正后计划开始时间 >= ?" params.append(filters[&#39;start_date&#39;]) if &#39;end_date&#39; in filters and filters[&#39;end_date&#39;]: query += " AND 修正后计划结束时间 <= ?" params.append(filters[&#39;end_date&#39;]) try: data = self.db_manager.query(query, params) logger.info(f"从 daily_output_plan_final 获取到 {len(data)} 条记录。") return data except Exception as e: logger.error(f"获取产出计划数据失败: {e}", exc_info=True) return []
最新发布
08-01
<think>我们注意到日志显示:从 daily_output_plan_final 获取到 0 条记录。 可能的原因: 1. 数据库连接问题:但日志显示已连接成功。 2. SQL脚本执行失败:在运行SQL脚本时可能出错,但日志中未捕获详细错误(需要检查日志中是否有执行SQL脚本的错误)。 3. 数据源表(work_orders, craft_data, part_category)中没有符合条件的数据。 4. SQL脚本逻辑导致没有数据插入到daily_output_plan_final。 我们已经在代码中捕获了执行SQL脚本的异常,并记录错误日志。因此,我们需要检查日志中是否有错误信息。 另外,我们注意到在运行SQL脚本之前,我们创建了表(如果不存在),然后执行整个脚本。脚本中第一步是删除表中的所有数据(DELETE FROM daily_output_plan_final;),然后插入新数据。 如果没有数据插入,可能是因为: a) 源表(work_orders)中没有数据,或者数据被过滤掉了(WHERE条件过滤)。 b) 递归CTE(CorrectedSchedule)执行失败(例如,递归深度过大或无限循环),但SQLite默认递归深度为1000,如果超过会报错。 建议步骤: 1. 检查日志中是否有执行SQL脚本的错误(logger.error(f"执行 SQL 脚本失败: {e}", exc_info=True))。 2. 检查源表(work_orders)中是否有数据,并且满足条件:(CAST(wo.taskQty AS REAL) > 0 AND (CAST(wo.outputQty AS REAL) / CAST(wo.taskQty AS REAL)) <= 0.9) 3. 检查其他关联表(craft_data, part_category)是否有数据。 如果日志中没有错误,但就是没有数据,我们可以尝试在SQL脚本中分段调试(但代码中已经是一个完整的脚本,无法在应用内分段执行)。 替代方案:在应用内逐步执行SQL脚本的各个部分,并检查每一步是否有数据。 但是,由于我们目前无法在应用内直接调试,我们可以考虑以下方法: 1. 在数据库中手动执行SQL脚本,观察错误或中间结果。 2. 在代码中增加中间步骤的日志输出,例如记录每一步CTE的行数。 然而,由于SQL脚本很长,我们可以在代码中不这样做,而是建议先手动执行脚本。 但是,我们也可以修改SQL脚本,在每一步CTE后插入日志记录(但SQLite不支持在CTE中记录日志)。因此,我们可以将中间结果保存到临时表,然后记录行数。 不过,考虑到时间,我们先检查日志中是否有错误。如果没有错误,那么可能是没有源数据。 另外,我们发现SQL脚本中有一个条件:WHERE (CAST(wo.taskQty AS REAL) > 0 AND (CAST(wo.outputQty AS REAL) / CAST(wo.taskQty AS REAL)) <= 0.9) 这个条件会过滤掉已完成90%以上的工单。如果我们的工单都已完成超过90%,那么就不会有数据。 因此,我们需要检查work_orders表中的数据。 如何检查?我们可以在执行SQL脚本之前,先执行一个查询,检查work_orders表中符合条件的数据。 修改代码:在process_and_save_daily_output_plan方法中,执行SQL脚本之前,先检查work_orders表中是否有数据。 但是,由于我们的SQL脚本很长,我们可以先手动执行一个简单的查询。 在代码中添加一个步骤:检查源表是否有数据。 修改后的process_and_save_daily_output_plan方法: ```python def process_and_save_daily_output_plan(self): """ 读取 SQL 脚本并执行,生成产出计划数据到 daily_output_plan_final 表。 """ if not os.path.exists(self.sql_script_path): logger.error(f"SQL 脚本文件未找到: {self.sql_script_path}") raise FileNotFoundError(f"SQL script not found at {self.sql_script_path}") # 先检查work_orders表中是否有数据 check_query = "SELECT COUNT(*) FROM work_orders" try: count = self.db_manager.query(check_query)[0][0] logger.info(f"work_orders表中有 {count} 条记录。") except Exception as e: logger.error(f"检查work_orders表失败: {e}", exc_info=True) return False # 再检查是否有满足条件的工单 condition_query = """ SELECT COUNT(*) FROM work_orders WHERE (CAST(taskQty AS REAL) > 0) AND (CAST(outputQty AS REAL) / CAST(taskQty AS REAL) <= 0.9) """ try: condition_count = self.db_manager.query(condition_query)[0][0] logger.info(f"work_orders表中有 {condition_count} 条满足条件的记录(未完成90%以上)。") except Exception as e: logger.error(f"检查满足条件的工单失败: {e}", exc_info=True) return False try: with open(self.sql_script_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f: sql_script = f.read() logger.info(f"开始执行 SQL 脚本: {self.sql_script_path}") self.db_manager.execute_script(sql_script) logger.info("产出计划数据已成功生成并保存到 daily_output_plan_final 表。") return True except Exception as e: logger.error(f"执行 SQL 脚本失败: {e}", exc_info=True) return False ``` 这样,我们可以在日志中看到源表的数据情况。 另外,我们还需要检查SQL脚本中其他部分,比如关联表(craft_data)是否有数据?如果关联不上,那么production_time可能为0,导致后续计算错误。 我们可以在PreparedData CTE中增加日志?但不行,因为是在同一个脚本中。 因此,我们可以在应用外手动执行整个SQL脚本,观察每一步的中间结果。 但是,由于应用已经集成,我们可以在代码中捕获SQL脚本执行时的异常,并打印出具体错误。 目前,我们的execute_script方法可能没有返回详细的错误信息。我们需要确保DatabaseManager中的方法能够抛出异常,并且我们在这里捕获并记录。 我们已经捕获了异常并记录,所以如果SQL脚本执行出错,我们会在日志中看到。 所以,请检查日志中是否有错误信息。 如果没有错误信息,但是也没有数据,那么可能是条件过滤导致没有数据插入。 另外,我们注意到在PreparedData中,我们使用了LEFT JOIN craft_data,如果找不到craft_data,则使用默认值。所以即使craft_data没有数据,也会使用默认值。 因此,我们首先检查work_orders表中是否有满足条件的数据。 如果满足条件的数据为0,那么我们需要调整条件或者导入数据。 如果满足条件的数据大于0,那么可能是SQL脚本中的递归CTE或其他部分导致没有数据。 由于递归CTE比较复杂,我们可以在数据库管理工具中手动执行整个SQL脚本,并逐步调试。 总结:我们在代码中添加了对源表数据的检查,这样可以帮助我们确定问题是否出在源数据上。 请尝试添加上述检查,并重新运行,查看日志输出。 另外,确保数据库中的work_orders表有数据,并且有满足条件(未完成90%以上)的工单。 如果问题仍然存在,请手动执行SQL脚本,观察执行情况。 手动执行步骤: 1. 用数据库工具(如DB Browser for SQLite)打开数据库文件。 2. 复制SQL脚本内容,执行整个脚本。 3. 观察是否有错误,或者查看每一步的中间结果(可以将中间CTE的结果插入临时表以便查看)。 由于SQL脚本很长,手动执行可能会遇到性能问题,但可以分段执行(例如,先执行到PreparedData,然后查询PreparedData的数据)。 如何分段?可以在PreparedData后面插入一条语句,将PreparedData的结果存入临时表,然后查询该临时表。 例如: ```sql WITH PreparedData AS (...), -- 将PreparedData的结果存入临时表 CREATE TEMP TABLE TempPreparedData AS SELECT * FROM PreparedData; ``` 然后查询TempPreparedData,看是否有数据。 同样,可以检查RankedData,CorrectedSchedule等。 这样逐步定位问题所在。 由于我们无法远程调试,以上方法需要本地进行。 在代码中,我们已经添加了对源数据的检查,这样至少可以知道是不是因为源数据不足导致。 请先按照上述修改代码,然后重新运行,查看日志。 如果源数据满足条件,但SQL脚本执行后还是没有数据,那么我们需要进一步调试SQL脚本。 另外,注意SQL脚本中递归CTE的终止条件:它依赖于global_rank的连续递增。如果global_rank不是从1开始连续递增,递归可能提前终止。 在RankedData中,我们使用ROW_NUMBER()生成global_rank,所以应该是连续的。但是,如果RankedData没有数据,那么递归CTE就不会有数据。 因此,我们首先确保PreparedData和RankedData有数据。 修改后的代码中,我们已经检查了work_orders中满足条件的数据,那么如果满足条件的数据>0,但RankedData中没有数据,可能是其他原因(如关联表、计算字段等)。 我们可以在PreparedData中检查是否有数据,通过临时表的方式(在应用中不便于做,所以建议手动执行)。 综上所述,我们先修改代码,添加对源数据的检查,然后根据日志输出再作判断。 修改后的OutputPlanModel代码:</think>您的代码显示数据库连接成功,但查询结果为空。这通常由以下几个原因导致: ### 问题分析 1. **数据源表为空**: - `work_orders` 表可能没有数据 - `craft_data` 表可能没有数据 - `part_category` 表可能没有数据 2. **SQL脚本执行失败**: - 脚本可能未正确执行 - 脚本中的过滤条件可能过滤掉了所有数据 3. **数据过滤条件**: - `WHERE (CAST(wo.taskQty AS REAL) > 0 AND (CAST(wo.outputQty AS REAL) / CAST(wo.taskQty AS REAL)) <= 0.9` 可能过滤了所有记录 4. **递归CTE问题**: - 递归查询可能因数据问题无法完成 ### 解决方案 #### 1. 添加数据验证和调试日志 在 `process_and_save_daily_output_plan` 方法中添加详细日志: ```python def process_and_save_daily_output_plan(self): # ... [原有代码] ... try: # 添加数据验证 logger.info("检查源表数据状态...") self._log_table_status("work_orders") self._log_table_status("craft_data") self._log_table_status("part_category") # 检查是否有满足条件的工单 condition_check = """ SELECT COUNT(*) FROM work_orders WHERE (CAST(taskQty AS REAL) > 0) AND (CAST(outputQty AS REAL) / CAST(taskQty AS REAL) <= 0.9 """ valid_count = self.db_manager.query(condition_check)[0][0] logger.info(f"满足条件的工单数量: {valid_count}") # 执行SQL脚本 with open(self.sql_script_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f: sql_script = f.read() logger.info(f"开始执行 SQL 脚本: {self.sql_script_path}") self.db_manager.execute_script(sql_script) # 检查执行结果 result_check = "SELECT COUNT(*) FROM daily_output_plan_final" result_count = self.db_manager.query(result_check)[0][0] logger.info(f"daily_output_plan_final 表记录数: {result_count}") logger.info("产出计划数据已成功生成并保存到 daily_output_plan_final 表。") return True except Exception as e: logger.error(f"执行 SQL 脚本失败: {e}", exc_info=True) return False def _log_table_status(self, table_name): """记录表的状态信息""" try: # 检查表是否存在 check_table = f"SELECT name FROM sqlite_master WHERE type=&#39;table&#39; AND name=&#39;{table_name}&#39;" exists = self.db_manager.query(check_table) if not exists: logger.warning(f"表 {table_name} 不存在") return # 获取记录数 count_query = f"SELECT COUNT(*) FROM {table_name}" count = self.db_manager.query(count_query)[0][0] # 获取列信息 columns_query = f"PRAGMA table_info({table_name})" columns = [col[1] for col in self.db_manager.query(columns_query)] logger.info(f"表 {table_name} - 记录数: {count}, 列: {&#39;, &#39;.join(columns)}") # 记录前5行数据样本 if count > 0: sample_query = f"SELECT * FROM {table_name} LIMIT 5" sample = self.db_manager.query(sample_query) logger.info(f"表 {table_name} 数据样本: {sample}") except Exception as e: logger.error(f"检查表 {table_name} 状态失败: {e}") ``` #### 2. 添加SQL脚本调试功能 创建脚本调试方法: ```python def debug_sql_script(self): """分步执行SQL脚本进行调试""" try: with open(self.sql_script_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f: sql_script = f.read() # 分割SQL脚本为独立的语句 statements = [stmt.strip() for stmt in sql_script.split(&#39;;&#39;) if stmt.strip()] logger.info(f"开始分步调试SQL脚本,共 {len(statements)} 条语句") for i, stmt in enumerate(statements, 1): try: logger.info(f"执行语句 {i}/{len(statements)}: {stmt[:100]}...") # 执行当前语句 self.db_manager.execute(stmt) # 如果是CTE查询,尝试获取中间结果 if "WITH" in stmt.upper() and "SELECT" in stmt.upper(): cte_name = stmt.split("AS")[0].split()[-1] if cte_name: try: sample = self.db_manager.query(f"SELECT * FROM {cte_name} LIMIT 5") logger.info(f"中间表 {cte_name} 样本数据: {sample}") except: pass logger.info(f"语句 {i} 执行成功") except Exception as e: logger.error(f"执行语句 {i} 失败: {e}") logger.error(f"失败语句: {stmt}") return False return True except Exception as e: logger.error(f"调试SQL脚本失败: {e}") return False ``` #### 3. 在调用代码中添加调试入口 在您的应用程序入口点添加调试选项: ```python # 在调用OutputPlanModel的地方 output_model = OutputPlanModel(db_manager) # 调试模式 if DEBUG_MODE: # 设置一个调试标志 # 检查表状态 output_model.process_and_save_daily_output_plan() # 分步调试SQL脚本 output_model.debug_sql_script() # 获取数据 data = output_model.get_output_plan_data() print(f"获取到的数据: {data}") else: # 正常执行 output_model.process_and_save_daily_output_plan() data = output_model.get_output_plan_data() ``` ### 常见问题解决方案 1. **源表无数据**: ```python # 模拟插入测试数据 test_data = """ INSERT INTO work_orders (prodplanId, workOrderNo, lineName, itemNo, itemName, taskQty, outputQty, scheduleStartDate, scheduleEndDate, actualStartDate, craftSection, order_index, remark, externalType, factoryName) VALUES (&#39;BATCH-001&#39;, &#39;WO-001&#39;, &#39;Line1&#39;, &#39;ITEM-001&#39;, &#39;Test Item&#39;, 1000, 200, &#39;2023-01-01 08:00:00&#39;, &#39;2023-01-05 17:00:00&#39;, &#39;2023-01-01 08:00:00&#39;, &#39;Assembly&#39;, 1, 1, &#39;TypeA&#39;, &#39;FactoryA&#39;), (&#39;BATCH-001&#39;, &#39;WO-002&#39;, &#39;Line1&#39;, &#39;ITEM-001&#39;, &#39;Test Item&#39;, 1000, 200, &#39;2023-01-01 08:00:00&#39;, &#39;2023-01-05 17:00:00&#39;, &#39;2023-01-01 08:00:00&#39;, &#39;Test&#39;, 2, 2, &#39;TypeA&#39;, &#39;FactoryA&#39;); """ db_manager.execute_script(test_data) ``` 2. **SQL脚本执行失败**: - 使用 `debug_sql_script()` 方法分步执行和调试 - 检查SQLite版本是否支持所有使用的功能(窗口函数、CTE等) 3. **数据库连接问题**: ```python # 在DatabaseManager中添加连接验证 def verify_connection(self): try: result = self.query("SELECT 1") return result[0][0] == 1 except Exception as e: logger.error(f"数据库连接验证失败: {e}") return False ``` ### 最终建议 1. 启用调试模式运行应用程序 2. 检查日志中的表状态信息 3. 使用 `debug_sql_script()` 分步执行SQL脚本 4. 根据日志信息添加测试数据或修复SQL脚本
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少卿不在大理寺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值