如何通过多进程/多线程终止卡住的Python爬虫方法,避免程序挂起
解决方案
直接使用multiprocessing搭配Queue做进程间结果传递,再加上轮询超时逻辑即可实现需求,同时给requests请求加上内置超时做双重保险,避免网络层无限挂起。
完整可运行代码
from multiprocessing import Process, Queue import time import requests from bs4 import BeautifulSoup url = "https://www.weerstationzoersel.be/weather2/index.php?p=10" def get_rain(queue): try: # 先给requests加9秒内置超时,做第一层兜底 response = requests.get(url, timeout=9) if response.status_code == 200: soup = BeautifulSoup(response.text, "html.parser") tags = soup.findAll('span') line_rain = str(tags[15]) line_rain = line_rain[62::] rainfall = line_rain.rstrip("</span>") rainfall = round(float(rainfall.replace(',','.')),1) queue.put(rainfall) return except Exception as e: pass queue.put("error") def get_rain_with_timeout(timeout=10): q = Queue() p = Process(target=get_rain, args=(q,)) p.start() # 每秒轮询一次,最多等timeout秒 for _ in range(timeout): time.sleep(1) if not p.is_alive(): # 进程已结束,取结果返回 res = q.get() p.join() return res # 超时,杀死进程 p.terminate() p.join() return "timeout" if __name__ == '__main__': # 单次调用测试 rainfall_data = get_rain_with_timeout() print(rainfall_data) # 如果要每小时定时执行,打开下面的注释即可 # while True: # rainfall_data = get_rain_with_timeout() # # 这里写你后续传入sprinkler服务、数据库的逻辑 # print(f"当前获取到的降雨量:{rainfall_data}") # # 等待1小时后下一次执行 # time.sleep(3600)
关键逻辑说明
- 子进程的返回值无法直接被主进程捕获,因此通过Queue传递爬取结果
- 内层给requests加了9秒超时,避免请求本身无限等待,外层10秒进程超时做最终兜底,双重保障不会挂死
- 轮询逻辑严格按照要求每秒检查一次进程状态,超时后立即终止进程释放资源,不会影响下一小时的定时任务
内容的提问来源于stack exchange,提问作者LARS VD
相关产品推荐
相关产品推荐

