M
M
Mamol272017-12-08 12:05:41
Python
Mamol27, 2017-12-08 12:05:41

Why don't threads in Python run in parallel?

I already dealt with multithreading in python, everything was fine.
The essence of the problem: there is a task to write a server that will interrogate various devices, which are described in the database in the corresponding table. Devices store parameters in themselves, on the basis of which control commands are sent to them, and the device must respond quickly as a result.
There are three methods that should work in parallel (not sequentially, because in case of a "No route to host" error, it waits for a response for 3 seconds): control_attractions, control_turnstiles and check_connect.
But the problem arose in that when launching one thread, it intercepts all the time on itself, maybe I missed something or I'm doing it wrong, please tell me.
My code:

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()

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question