You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过多进程/多线程终止卡住的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 19:51:03