Answer the question
In order to leave comments, you need to log in
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:
# -*- 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 questionAsk a Question
731 491 924 answers to any question