0

Hey I am runnig my python code under Linux on a Raspberry Pi and it consists of a main.py file that opens threads to do various tasks

For more insights: my filestructure looks like this: main.py modules ----controller.py ----server.py ----reader.py ----logger.py ----dbhandling.py

-the controller has a loop in witch it looks for new entrys in the database and reacts to them -the server is just a flask application -the logger has a cons_log() function in which I can output data in the same format to the terminal. It uses termcolor, which doesnt work with the coderunner output, thats why there is this weird asci shown sometimes -the dbhandler is just there to read and write the db conveiniently -the reader reads out a rfid reader via the raspberrypi gpio. It listens all the time for new rfid tags.

The whole main.py looks like this:

import time
import threading
from datetime import datetime


from modules.server import Serv
from modules.logger import cons_log
from modules.reader import ReaderInteraction as ReaderI
from modules.controller import ControllerLoop
from modules.dbhandling import DBinteractions as Db

while True:
    try:
        cons_log("MAIN", "Starting ControllerLoop...", "yellow", "0")
        controller_threat = threading.Thread(target=ControllerLoop().loop)
        controller_threat.name = "Controller Threat"
        controller_threat.start()
        time.sleep(1)
        cons_log("MAIN", "Successfully started ControllerLoop", "green", "202")
        controller_threat.join()
        break
    except Exception as e:
        cons_log(
            "MAIN", "Could not start ControllerLoop, Error: \n" + str(e), "red", "404"
        )
        time.sleep(5)

while True:
    try:
        cons_log("MAIN", "Starting Server...", "yellow", "0")
        server_threat = threading.Thread(target=Serv)
        server_threat.name = "Server Threat"
        server_threat.start()
        time.sleep(1)
        cons_log("MAIN", "Successfully started Server", "green", "202")
        server_threat.join()
        break
    except Exception as e:
        cons_log("MAIN", "Could not start Server, Error: \n" + str(e), "red", "404")
        time.sleep(5)

while True:
    try:
        cons_log("MAIN", "Starting Reader...", "yellow", "0")
        reader_threat = threading.Thread(target=ReaderI().runreader)
        reader_threat.name = "Reader Threat"
        reader_threat.start()
        time.sleep(1)
        cons_log("MAIN", "Successfully started Reader", "green", "202")
        reader_threat.join()
        break
    except Exception as e:
        cons_log("MAIN", "Could not start Reader, Error: \n" + str(e), "red", "404")
        time.sleep(5)



The controller looks like this:

# module used to control the hardware and electric systems via constant database readouts
import RPi.GPIO as GPIO
import time

class ControllerLoop:
    def __init__(self):
        None

    def loop(self):
        while True:
            time.sleep(0.3)
            # check for new controlls to do based on entrys in database

The server looks like this:

from flask import Flask, flash

def Serv():
    app = Flask(__name__, template_folder="../templates")
    # all the routs in here
    app.secret_key = "tpsecret..."

    app.run(debug=False, port=8000, host="0.0.0.0")

The reader looks like this:

import time
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522

class ReaderInteraction:
    def __init__(self):
        self.reader = SimpleMFRC522()

    def runreader(self):
        while True:
            try:
                id, text = self.reader.read()
                print(id)
                time.sleep(1)
            finally:
                GPIO.cleanup()

The logger looks like this:

from datetime import datetime
from termcolor import colored
from time import time
from flask import Flask, redirect, flash, url_for


def cons_log(process, message, color, code):
    flask_ip = "127.0.0.1"
    time = datetime.today()
    print(
        flask_ip
        + " - - ["
        + time.today().strftime("%d/%m/%Y")
        + " "
        + time.today().strftime("%H:%M:%S")
        + "] "
        + '"'
        + colored(process + " " + message + '"', color)
        + " "
        + code
        + "-"
    )


def flask_log(process, message, color, code, flashmsg, flashtype, redir):
    # def to communicate with user
    flask_ip = "127.0.0.1"
    time = datetime.today()
    print(
        flask_ip
        + " - - ["
        + time.today().strftime("%d/%m/%Y")
        + " "
        + time.today().strftime("%H:%M:%S")
        + "] "
        + '"'
        + colored(process + " " + message + '"', color)
        + " "
        + code
        + "-"
    )
    flash(flashmsg, flashtype)
    return redirect(url_for(redir))

When using .join() at the end of the main.py for all threads the output stops after the first .join() call.

Question: If I use the .join() on the controllerloop does the main program then waits with the execution of the next code untill the controllerloop is finished? Because if so the controllerloop is running endless and the main would never continue right?

  • 2
    Your main thread ends while the other thread is still running. You should do a `reader_threat.join()` at the end of your main thread. – Klaus D. Jun 10 '20 at 11:59
  • But shouldnt that be also true for the execution in the terminal then? – Moritz Pfennig Jun 10 '20 at 12:11
  • That depends on the environment and its thread handling. The second thread in the first case might be ended by a signal when the first dies. – Klaus D. Jun 10 '20 at 12:16
  • Hm, I just tried to integrate the .join() but when I do my program stops after I cll the first of the 3 .join() functions. Do you know why that happens? – Moritz Pfennig Jun 10 '20 at 12:20
  • Which 3 functions? – Klaus D. Jun 10 '20 at 12:22
  • Please provide some more details. The thread obviously yields *some* output, as indicated by the ``Reader Loop``. It appears that ``cons_log`` inserts ANSI escape sequences, which are not properly interpreted in the first case – does the issue also occur when not using ``cons_log``? Also, the Thread ``target`` is a method of ``ReaderI``, but the class shown is called ``ReaderInteraction`` - is the code of ``ReaderInteraction.runreader`` shown the actual code run? – MisterMiyagi Jun 10 '20 at 12:34
  • I just expanded my question with all the code! – Moritz Pfennig Jun 10 '20 at 12:55
  • What does ``self.reader.read()`` do? The loop will not print again if this call blocks. Please consider to create a [mcve]; the chance of getting help increases immensely if volunteer helpers can understand your code. – MisterMiyagi Jun 10 '20 at 12:57
  • the self.reader.read() is from the mfrc522 libary and reads out the rfid tag if a tag is detected. I didnt do a lot of looking into the libary yet so I dont quite understand how it works in detail. What steps should I do to get a reprex? I dont know if I can shorten it any further. – Moritz Pfennig Jun 10 '20 at 13:03
  • Concerning the reprex: Judging from your description, you seem to assume the issue is using ``print`` inside a ``Thread`` when running the program through code-runner. You should create a reprex for *just this* (minus the code-runner, since it is not Python) – the initial code was already close, but should remove the outer ``while True``, the class, and ``cons_log``. If this reprex does not reproduce the problem *when you run it using code-runner*, you can rule out print+Thread being the issue. That means we can focus on the actual problem, or ignore `mfrc522` and further compleixities. – MisterMiyagi Jun 10 '20 at 13:07
  • Ok, I reviewed the question and edited some things and deleted unneccesary parts – Moritz Pfennig Jun 10 '20 at 13:23

0 Answers0