首页 > 解决方案 > Python:关闭多处理线程会停止整个程序

问题描述

我已经在 python 中编程了一段时间,但这是我在多处理方面的第一次。

我制作了一个程序,每分钟使用 beautifulsoup4 抓取当地气象站的环境温度。该程序还从多个传感器读取温度并将所有内容上传到 Mysql 数据库。这一切都很好,但有时(每天一次)从当地气象站获取数据无法检索网页。这会导致 beautifulsoup 启动一个无限循环,从而有效地停止程序的所有功能。为了解决这个问题,我尝试尝试多处理。

我编写了一个检查,如果 10 秒后仍在运行,则会杀死额外的线程。这是出现问题的地方,通常,beautifulsoup 线程在完成后 2-4 秒后关闭。然而,如果 beautifulsoup 卡在其循环中,不仅线程会终止,而且整个程序也会完全停止执行操作。

我已经复制了相关的代码片段。请注意,一些变量是在代码片段之外声明的,除了上述问题之外,代码都可以工作。顺便说一句,我非常清楚有很多方法可以使我的代码更高效。优化代码是我会在它工作稳定时做的事情:) 在此先感谢您的帮助!

进口:

...    
from multiprocessing import Process, Queue
import multiprocessing
from bs4 import BeautifulSoup #sudo apt-get install python3-bs4

Beutifulsoup 部分:

def get_ZWS_temp_out(temp):
    try:
        if 1==1:
            response = requests.get(url)
            responsestr = str(response)
            if "200" in responsestr:
                soup = BeautifulSoup(response.content, 'html.parser')
                tb = soup.findAll("div", {"class": "elementor-element elementor-element-8245410 elementor-widget__width-inherit elementor-widget elementor-widget-wp-widget-live_weather_station_widget_outdoor"})
                tb2 = tb[0].findAll("div", {"class": "lws-widget-big-value"})
                string = str(tb2[0])[-10:][:4]
                stringt = string[:1]
                if stringt.isdigit() == True:
                    #print("getal ok")
                    string = string
                elif stringt == '-':
                    #print("minteken")
                    string = string
                elif stringt == '>':
                    #print("temp < 10")
                    string = string[-3:]
                temp = float(string)

    except Exception as error:
        print(error)
    Q.put(temp)       
    return(temp)

主程序:

 Q = Queue()
while 1 == 1:
    strings = time.strftime("%Y,%m,%d,%H,%M,%S")
    t = strings.split(',')
    time_numbers = [ int(x) for x in t ]
    if last_min != time_numbers[4]:
        targettemp = get_temp_target(targettemp)
        p = Process(target=get_ZWS_temp_out, name="get_ZWS_temp_out", args=(ZWS_temp_out,))
        p.start()
        i = 0
        join = True
        while i < 10:
            i = i + 1
            time.sleep(1)
            if p.is_alive() and i == 10: #checks to quit early otherwise another iteration
                print(datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d %H:%M:%S"),": ZWS getter is running for too long... let's kill it...")
                # Terminate ZWS query
                p.terminate()
                i = 10
                join = False
        if join == True:
            p.join()

在此先感谢您的时间 :)

我必须手动停止提供以下输出的程序:

pi@Jacuzzi-pi:~ $ python3 /home/pi/Jacuzzi/thermometer.py
temperature sensors observer and saving program, updates every 3,5 seconds
2019-10-28 03:50:11 : ZWS getter is running for too long... let's kill it...
^CTraceback (most recent call last):
  File "/home/pi/Jacuzzi/thermometer.py", line 283, in <module>
    ZWS_temp_out = Q.get()
  File "/usr/lib/python3.5/multiprocessing/queues.py", line 94, in get
    res = self._recv_bytes()
  File "/usr/lib/python3.5/multiprocessing/connection.py", line 216, in recv_bytes
    buf = self._recv_bytes(maxlength)
  File "/usr/lib/python3.5/multiprocessing/connection.py", line 407, in _recv_bytes
    buf = self._recv(4)
  File "/usr/lib/python3.5/multiprocessing/connection.py", line 379, in _recv
    chunk = read(handle, remaining)
KeyboardInterrupt

标签: python-3.xbeautifulsoupmultiprocessing

解决方案


我相信您的程序正在无限等待从您创建的队列中提取项目。我在您发布的代码中看不到该行,但它出现在错误消息中:

ZWS_temp_out = Q.get()

由于get_ZWS_temp_out进程是将项目添加到队列中的进程,因此您需要在调用之前确保该进程正在运行Q.get()。我怀疑这行代码是在终止超时进程和重新启动新进程之间执行的,而应该在创建新进程后调用它。


推荐阅读