Python: Закрытие многопроцессорного потока останавливает всю программу - PullRequest
1 голос
/ 27 октября 2019

Я некоторое время программировал на 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

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

На основании того, что Роб обнаружил, это обновленный (рабочий) код для основной программы, остальные без изменений:

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
        completion = 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
                completion = False
        if completion == True:
            p.join()
            ZWS_temp_out = Q.get()
0 голосов
/ 28 октября 2019

Я полагаю, что ваша программа бесконечно ждет извлечения элементов из созданной вами очереди. Я не вижу строки в коде, который вы опубликовали, но он появляется в сообщении об ошибке:

ZWS_temp_out = Q.get()

Поскольку процесс get_ZWS_temp_out добавляет элементы в очередь, вам нужночтобы убедиться, что процесс запущен, перед вызовом Q.get(). Я подозреваю, что эта строка кода выполняется между завершением процесса ожидания и перезапуском нового процесса, где вместо этого он должен вызываться после создания нового процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...