Задать вопрос
@Mamol27

Почему потоки в Python не работают параллельно?

С многопоточностью в питоне уже имел дело, все было хорошо.
Суть проблемы: есть задание написать сервер, который будет опрашивать различные устройства, что описаны в бд в соответствующей табличке. Устройства в себе хранят параметры, на основе которых им отсылаются управляющие команды и устройство должно быстро откликаться в итоге.
Есть три метода, которые должны работать параллельно (последовательно нельзя так как в случае ошибки "No route to host" идет ожидание ответа 3 секунды): control_attractions, control_turnstiles и check_connect.
Но проблема возникла в том что запуская один поток, он перехватывает все время на себя, возможно я что-то упустил или делаю неверно, подскажите пожалуйста.
Мой код:
spoiler
# -*- coding: utf-8 -*-
# from imp import reload

from model.modbus import ModbusMaster
from model.dataBase import DataBase
import model.defines as dfs
from time import sleep
from datetime import datetime
import logging
import threading


class Main:

    def __init__(self):

        self.base = DataBase()
        self.mod_slave = ModbusMaster()

        # ((id, name, ip, players, score_is_time),
        # (id, name, ip, players, score_is_time), ...)
        self.base_attractions = self.base.load_attr()
        self.attractions = []
        self.attractions_lock = threading.Lock()
        self.games = {}
        # ((id, ip, direction_in), ...)
        self.turnstiles = self.base.load_turnstiles()

        self.threading_check = None
        self.threading_turnstiles = None
        self.is_threading_check_connect = False
        self.is_threading_turnstiles = False

        self.init_logs()
        self.init_games()

    def init_games(self):
        for i in self.base_attractions:
            players = []
            for j in range(i[3]):
                players.append(0)
            if not self.games.keys().__contains__(i[0]):
                self.games[i[0]] = players

    def init_logs(self):
        dt = datetime.now()
        date = dt.strftime("%d.%m.%y-%H:%M")

        self.logger = logging.getLogger("mainApp")
        self.logger.setLevel(level=logging.INFO)
        # create the logging file handler
        fh = logging.FileHandler(".././logs/{} - error.log".format(date))

        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)

        # add handler to logger object
        self.logger.addHandler(fh)

    def check_connect(self):
        modbus = ModbusMaster()
        while self.is_threading_check_connect:
            print("check")
            attractions_connect = []
            for row in self.base_attractions:
                try:
                    modbus.read_registers(host=row[2], address=dfs.MODBUS_FIRST_REG, count=1)
                    attractions_connect.append(row)
                except Exception as e:
                    pass

            self.attractions_lock.acquire(1)
            self.attractions = attractions_connect[:]
            self.attractions_lock.release()

            sleep(5)

    def launch_attractions(self, row, id_card, cg, isAdmin):
        self.mod_slave.write_register(dfs.MODBUS_FIRST_REG + dfs.GAME_START, dfs.MODBUS_START_GAME, row[2])
        self.mod_slave.write_registers(dfs.GAME_AVERAGE, [self.base.get_avg_score(row[0]),
                                                          self.base.get_best_score(row[0], row[4]),
                                                          self.base.get_grown(id_card),
                                                          self.base.get_age(id_card)],
                                       row[2])
        if not isAdmin:
            self.base.update_count_games(cg - 1, id_card, row[0])
        self.games[row[0]][0] = id_card

    def control_attractions(self):
        self.attractions_lock.acquire(1)
        for row in self.attractions:
            try:
                table = self.mod_slave.read_registers(host=row[2], address=dfs.MODBUS_FIRST_REG, count=dfs.MODBUS_COUNT_REG)
                id_card = table[dfs.GAME_UID_LOW]
                id_card <<= 16
                id_card |= table[dfs.GAME_UID_HIGH]

                if table[dfs.GAME_STEP] == dfs.STEP_STANDBY:
                    if id_card > 0 and self.games[row[0]][0] == 0:
                        cg = self.base.veify_player(id_card, row[0])
                        if cg > 0:
                            self.launch_attractions(row, id_card, cg, 0)

                    elif cg < 0 and self.games[row[0]][0] == 0:
                        self.launch_attractions(row, id_card, cg, 1)

                elif table[dfs.GAME_STEP] == dfs.STEP_PRESTART and row[3] > 1 \
                        and self.games[row[0]][0] != id_card and self.games[row[0]][1] == 0:
                    if id_card > 0:
                        cg = self.base.veify_player(id_card, row[0])
                        if cg > 0 and self.games[row[0]][1] == 0:
                            # mod_slave.write_register(dfs.MODBUS_FIRST_REG, dfs.MODBUS_START_GAME, row[2])
                            self.base.update_count_games(cg - 1, id_card, row[0])
                            self.games[row[0]][1] = id_card
                        elif cg < 0 and self.games[row[0]][1] == 0:
                            # mod_slave.write_register(dfs.MODBUS_FIRST_REG, dfs.MODBUS_START_GAME, row[2])
                            self.games[row[0]][1] = id_card

                elif table[dfs.GAME_STEP] == dfs.STEP_GAME_OVER:
                    if len(self.games[row[0]]) > 1:
                        if self.games[row[0]][1] is not 0:
                            if self.base.update_game_score(table[dfs.GAME_SCORE_2], self.games[row[0]][1], row[0]):
                                self.games[row[0]][1] = 0
                    if self.games[row[0]][0] is not 0:
                        if self.base.update_game_score(table[dfs.GAME_SCORE], self.games[row[0]][0], row[0]):
                            self.games[row[0]][0] = 0

            except ConnectionRefusedError as e:
                self.logger.error("Code=%d - %s" % (e.errno, str(e)))
                pass

            except OSError as e:
                self.logger.error("Code=%d - %s" % (e.errno, str(e)))
                pass

        self.attractions_lock.release()

    def control_turnstiles(self):
        modbus_tur = ModbusMaster()
        base_tur = DataBase()
        while self.is_threading_turnstiles:
            for row in self.turnstiles:
                try:
                    print("try turnstiles")
                    table = modbus_tur.read_registers(host=row[1], address=dfs.MODBUS_FIRST_REG, count=dfs.TUR_MOD_COUNT_REG)
                    id_card = table[dfs.TUR_UID_LOW]
                    id_card <<= 16
                    id_card |= table[dfs.TUR_UID_HIGH]
                    is_inside = base_tur.where_person(id_card)

                    if id_card > 0:
                        if row[2] != is_inside:
                            modbus_tur.write_register(dfs.MODBUS_FIRST_REG + dfs.TUR_MOD_ACCEPT, 1, row[1])
                except:
                    # self.logger.error("problem with turnstiles")
                    pass
            sleep(.5)

    def main(self):

        self.is_threading_check_connect = True
        self.threading_check = threading.Thread(target=self.check_connect())
        self.threading_turnstiles = threading.Thread(target=self.control_turnstiles())

        self.is_threading_turnstiles = True

        self.threading_check.start()
        self.threading_turnstiles.start()
        while 1:
            try:
                self.control_attractions()
                # self.control_turnstiles()
                sleep(.5)
                print("main loop")

            except KeyboardInterrupt as e:
                self.is_threading_check_connect = False
                self.is_threading_turnstiles = False
                self.threading_check.join()
                self.threading_turnstiles.join()
                self.logger.error("%s" % e)
                break

            except OSError as e:
                self.logger.error("%s" % e)
                pass

            except Exception as e:
                self.logger.error("%s" % e)
                break


def main():
    lp = Main()
    lp.main()


if __name__ == '__main__':
    main()
  • Вопрос задан
  • 637 просмотров
Подписаться 1 Простой 2 комментария
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы