Python多线程URL爬取任务卡在最后一个任务的问题求助
可能的原因及排查方向
1. 字符串格式化的低级错误
你的send_request和logic_a调用中错误使用了f-string:
res = send_request(f"input_tuple[1]") some_data = logic_a(f"input_tuple[1]")
这里的写法会把input_tuple[1]当作字面量字符串传递给接口,而不是取元组的第二个元素(实际URL)。正确写法应该是直接传入变量:
res = send_request(input_tuple[1]) some_data = logic_a(input_tuple[1])
这个错误会导致大部分请求调用无效地址,直接返回None,部分任务的异常行为可能间接引发后续阻塞。
2. 日志记录代码的规范问题
logging.info("error in main: ", e)不符合logging模块的使用规范,应该用格式化字符串传递异常信息:
logging.info("error in main: %s", e) # 或者使用f-string logging.info(f"error in main: {e}")
原写法中,e会被当作额外参数处理,如果e的类型无法被正确格式化,会在异常处理块中抛出新的未捕获异常——而executor.map的迭代器会在遍历到对应任务时才暴露这个异常,导致遍历过程卡住。
3. 数据库操作的阻塞或死锁
logic_a中的数据库写入操作可能存在以下问题:
- 未提交事务:如果开启了事务但忘记提交,数据库连接会被持续占用,线程看似执行完日志,实际卡在事务等待环节。
- 连接池耗尽:未正确复用或关闭数据库连接,多次迭代后连接池被占满,后续任务的DB操作阻塞。
- 数据库死锁:多线程同时写入时出现行锁/表锁冲突,导致线程阻塞无法完成。
即使日志在logic_a之后输出,也不代表数据库操作已完全完成(部分驱动的写入是异步提交的)。
4. 隐性的任务阻塞
main函数中可能存在未处理的阻塞逻辑:
send_request未设置超时,某个URL的请求一直挂起,线程看似执行完日志但实际卡在IO等待。logic_a的HTML解析或DB操作存在未被捕获的死循环、阻塞调用。with ThreadPoolExecutor块退出时会等待所有任务完成,只要有一个任务未真正结束,整个块就会一直阻塞,后续的for result in results自然无法执行。
5. 迭代器遍历的异常未被捕获
executor.map返回的是迭代器,遍历它时才会逐个返回结果或抛出异常。如果某组任务中存在未被main捕获的异常,遍历到该位置时程序会终止或卡住。可以给遍历逻辑加一层异常捕获:
try: for result in results: print(result) except Exception as e: logging.error(f"Error when iterating results: {e}")
内容的提问来源于stack exchange,提问作者tom
相关产品推荐
相关产品推荐

