# Bug 报告 ## 严重程度说明 - 🔴 **严重**: 可能导致程序崩溃或数据丢失 - 🟡 **中等**: 可能导致功能异常或错误处理不当 - 🟢 **轻微**: 代码质量问题,不影响功能但需要改进 --- ## 1. api.py (根目录) - 错误日志键名错误 ### 位置 - 第540行:`entry_data_batch_delete` 方法 - 第654行:`workflow_task_hand_over` 方法 - 第701行:`get_upload_token` 方法 - 第745行:`upload_file` 方法 ### 问题描述 🟡 **中等** - 在错误日志中使用了错误的键名 `data['data_list']`,但这些方法中可能不存在该键。 ### 代码示例 ```python # 第540行 - entry_data_batch_delete error_task_logger.error( f"任务 {data['data_list'][start_index:end_index]} 连续{max_retries}次请求失败,放弃此次请求。") # 应该是 data['data_ids'] # 第654行 - workflow_task_hand_over error_task_logger.error( f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。") # 该方法没有 data_list 键 # 第701行 - get_upload_token error_task_logger.error( f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。") # 该方法没有 data_list 键 # 第745行 - upload_file error_task_logger.error( f"任务 {data['data_list']} 连续{max_retries}次请求失败,放弃此次请求。") # 该方法没有 data_list 键 ``` ### 修复建议 使用正确的键名或使用 `data.get()` 方法安全访问。 --- ## 2. main.py - Handler 调用问题 ### 位置 第76行和第80行 ### 问题描述 🟡 **中等** - 当 `action_map.get()` 返回默认的 lambda 函数时,handler 是一个函数对象,但代码中直接将其传递给 `enqueue_task`,这应该是正确的。但如果 handler 是 lambda,需要确保它能被正确调用。 ### 代码示例 ```python # 第76行 handler = action_map.get(sub_action, lambda x: {'msg': '未执行'}) # 第80行 handler = action_map.get(action, lambda x: {'msg': '未知的操作'}) ``` ### 修复建议 确保所有 handler 都能正确处理数据参数。如果 handler 可能返回 None,需要添加检查。 --- ## 3. main.py - 队列阻塞风险 ### 位置 第86行 ### 问题描述 🟡 **中等** - 使用 `response_queue.get()` 会无限期阻塞,如果任务处理线程出现问题,可能导致请求永远挂起。 ### 代码示例 ```python result = await anyio.to_thread.run_sync(response_queue.get) ``` ### 修复建议 添加超时机制或使用 `response_queue.get(timeout=...)`。 --- ## 4. app/api.py - 数组访问未检查 ### 位置 第712-713行:`get_upload_token` 方法 ### 问题描述 🔴 **严重** - 直接访问 `res_j['token_and_url_list'][0]` 可能导致 KeyError 或 IndexError。 ### 代码示例 ```python res_j = res.json() upload_url = res_j['token_and_url_list'][0]['url'] upload_token = res_j['token_and_url_list'][0]['token'] ``` ### 修复建议 添加检查: ```python token_list = res_j.get('token_and_url_list', []) if not token_list: raise ValueError("未获取到上传凭证") upload_url = token_list[0].get('url') upload_token = token_list[0].get('token') ``` --- ## 5. app/module/F6_Plugin_module.py - 数组访问未检查 ### 位置 第40行:`accept_file` 方法 ### 问题描述 🔴 **严重** - 直接访问 `data['data']['附件'][0]['url']` 可能导致 KeyError 或 IndexError。 ### 代码示例 ```python url = data['data']['附件'][0]['url'] ``` ### 修复建议 添加检查: ```python attachments = data.get('data', {}).get('附件', []) if not attachments: return None, data url = attachments[0].get('url') ``` --- ## 6. app/module/F6_Plugin_module.py - 键访问未检查 ### 位置 第96行:`check_file` 方法 ### 问题描述 🔴 **严重** - 直接访问 `data1['data']['Action(隐藏)']` 可能导致 KeyError。 ### 代码示例 ```python action = data1['data']['Action(隐藏)'] ``` ### 修复建议 使用安全访问: ```python action = data1.get('data', {}).get('Action(隐藏)') if not action: return {'msg': '缺少Action字段'} ``` --- ## 7. app/module/module.py - 临时文件未清理 ### 位置 第21-31行:`get_captcha` 方法 ### 问题描述 🟢 **轻微** - 创建了临时文件 `captcha.png` 和 `preprocessed_captcha.png`,但没有清理。 ### 代码示例 ```python with open('captcha.png', 'wb') as f: f.write(response.content) # ... 处理文件 ... image.save('preprocessed_captcha.png') ``` ### 修复建议 使用临时文件或处理完后删除: ```python import tempfile import os with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as tmp: tmp.write(response.content) tmp_path = tmp.name try: # 处理文件 ... finally: if os.path.exists(tmp_path): os.remove(tmp_path) ``` --- ## 8. app/module/module.py - group_id 可能为空 ### 位置 第65-73行:`login_in` 方法 ### 问题描述 🟡 **中等** - 如果找不到匹配的 `company_name`,`group_id` 为空字符串,后续请求可能失败。 ### 代码示例 ```python group_id = '' for group in res_json.get('data', []): if group["groupName"] == company_name: group_id = group.get("groupId") token = quote(res_json['token']) url = (f'https://yunxiu.f6car.cn/kzf6/user/loginAfterChooseGroup?' f'token={token}&groupId={group_id}&macAddress=') ``` ### 修复建议 添加检查: ```python if not group_id: logger.error(f"未找到公司名称: {company_name}") return None ``` --- ## 9. app/module/module.py - 时间判断逻辑错误 ### 位置 第119行:`delete_customer_background` 方法(在 delete_tasks.py 中) 第246行:`delete_car_background` 方法(在 delete_tasks.py 中) ### 问题描述 🟡 **中等** - 时间判断逻辑错误:`if 20 <= now.hour <= 8:` 永远不会为 True(20 不可能小于等于 8)。 ### 代码示例 ```python now = datetime.now() if 20 <= now.hour <= 8: time.sleep(1) else: time.sleep(3) ``` ### 修复建议 应该是: ```python now = datetime.now() if 8 <= now.hour <= 20: # 8点到20点之间 time.sleep(3.5) else: # 其他时间 time.sleep(1.5) ``` --- ## 10. app/tasks/common.py - 数组访问未检查 ### 位置 第56行:`approve_workflow` 方法 ### 问题描述 🔴 **严重** - 直接访问 `json['tasks']` 和 `json['tasks'][0]` 可能导致 KeyError 或 IndexError。 ### 代码示例 ```python for task in json['tasks']: if task['status'] == 0: username = task['assignee']['username'] instance_id = task['instance_id'] task_id = task['task_id'] ``` ### 修复建议 添加检查: ```python tasks = json.get('tasks', []) if not tasks: logger.error("未找到待处理任务") return for task in tasks: if task.get('status') == 0: assignee = task.get('assignee', {}) username = assignee.get('username') instance_id = task.get('instance_id') task_id = task.get('task_id') if username and instance_id and task_id: break ``` --- ## 11. app/tasks/delete_tasks.py - 数组访问未检查 ### 位置 第62行:`delete_customer_background` 方法 第154行:`delete_car_background` 方法 ### 问题描述 🔴 **严重** - 直接访问 `org_res.json().get("data").get("list")[0]` 可能导致 IndexError。 ### 代码示例 ```python operate_org_id = org_res.json().get("data").get("list")[0].get("orgId") ``` ### 修复建议 添加检查: ```python org_data = org_res.json().get("data", {}).get("list", []) if not org_data: logger.error("未获取到门店信息") return operate_org_id = org_data[0].get("orgId") ``` --- ## 12. app/tasks/customer_tasks.py - 重试逻辑错误 ### 位置 第52-67行:`modify_customer_info_background` 方法 ### 问题描述 🟡 **中等** - `retry_count` 在循环外部初始化,导致每次页面请求都使用相同的重试计数,而不是每页独立重试。 ### 代码示例 ```python retry_count = 0 for page in range(1, total_pages + 1): while retry_count < max_retries: # ... if response.status_code == 200: break else: retry_count += 1 ``` ### 修复建议 将 `retry_count` 移到循环内部: ```python for page in range(1, total_pages + 1): retry_count = 0 while retry_count < max_retries: # ... ``` --- ## 13. app/tasks/delete_tasks.py - 条件判断错误 ### 位置 第115-116行:`delete_customer_background` 方法 ### 问题描述 🟡 **中等** - `if success + fail < len(json_data):` 这个条件判断逻辑有问题,应该检查是否还有未处理的项。 ### 代码示例 ```python if success + fail < len(json_data): continue ``` ### 修复建议 这个条件判断似乎是想检查是否处理完所有项,但逻辑不正确。应该移除或修正。 --- ## 14. app/tasks/delete_tasks.py - 变量作用域问题 ### 位置 第215行:`delete_car_background` 方法 ### 问题描述 🟡 **中等** - 在循环外部使用了 `page` 变量,但 `page` 只在循环内部定义。 ### 代码示例 ```python for page in range(1, all_page + 1): # ... for item in items: # ... if not car_id or not customer_id: logger.info(f"页码 {page} 中缺少必要的ID信息") # page 在这里可用 # ... # ... logger.error(f"删除失败: 页码 {page}, ...") # page 在这里可用 ``` 实际上这个不是bug,`page` 在循环内部是可用的。但如果在循环外部使用就会有问题。 --- ## 15. api.py (根目录) - 文件资源泄漏 ### 位置 第721-747行:`upload_file` 方法 ### 问题描述 🔴 **严重** - 文件在循环外部打开,如果循环中发生异常或提前返回,文件可能不会被关闭,导致资源泄漏。 ### 代码示例 ```python f = open(file_path, 'rb') files = {"file": f} retries = 0 while retries <= max_retries: try: res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10) # ... if res.status_code == 200: return data_get # 提前返回,文件未关闭! # ... except requests.exceptions.RequestException as e: # 如果异常发生,文件可能不会被关闭 # ... f.close() # 只有在循环结束后才会执行 ``` ### 修复建议 使用 `with` 语句确保文件总是被关闭: ```python retries = 0 result = None while retries <= max_retries: try: with open(file_path, 'rb') as f: files = {"file": f} res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10) res.raise_for_status() data_get = res.json() if res.status_code == 200: return data_get retries += 1 time.sleep(3) except requests.exceptions.RequestException as e: logger.warning(f"请求异常: {e}, 将重新请求") retries += 1 time.sleep(3) if retries > max_retries: error_task_logger.error(f"上传文件失败,已重试{max_retries}次") return None ``` --- ## 16. api.py (根目录) - 重试时文件指针问题 ### 位置 第721-747行:`upload_file` 方法 ### 问题描述 🟡 **中等** - 文件在循环外部打开,重试时文件指针已经移动到文件末尾,后续重试会读取空内容。 ### 代码示例 ```python f = open(file_path, 'rb') files = {"file": f} retries = 0 while retries <= max_retries: res = requests.post(url=url, data=payload, headers=headers, files=files, timeout=10) # 第一次请求后,文件指针已经移动到末尾 # 重试时会读取空内容 ``` ### 修复建议 每次重试时重新打开文件,或使用 `with` 语句在每次循环中打开文件。 --- ## 总结 ### 按严重程度分类 **严重 (🔴)** - 需要立即修复: 1. app/api.py - 数组访问未检查(get_upload_token) 2. app/module/F6_Plugin_module.py - 数组访问未检查(accept_file) 3. app/module/F6_Plugin_module.py - 键访问未检查(check_file) 4. app/tasks/common.py - 数组访问未检查(approve_workflow) 5. app/tasks/delete_tasks.py - 数组访问未检查(两处) 6. api.py (根目录) - 文件资源泄漏(upload_file) **中等 (🟡)** - 建议尽快修复: 1. api.py - 错误日志键名错误(多处) 2. api.py - 重试时文件指针问题(upload_file) 3. main.py - Handler 调用和队列阻塞问题 4. app/module/module.py - group_id 可能为空 5. app/module/module.py - 时间判断逻辑错误(两处) 6. app/tasks/customer_tasks.py - 重试逻辑错误 7. app/tasks/delete_tasks.py - 条件判断错误 **轻微 (🟢)** - 代码质量改进: 1. app/module/module.py - 临时文件未清理 ### 建议的修复优先级 1. **立即修复**:所有严重级别的bug,特别是可能导致程序崩溃的数组访问问题 2. **尽快修复**:中等级别的bug,特别是逻辑错误和错误处理问题 3. **代码改进**:轻微级别的bug,在时间允许时进行改进