Python Forum

Full Version: Method works as expected on host machine but not on server
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Good morning,

I have written the following script, which should run a method recursively until the constant SIGN_COLOR from an external .ini file is RED.

#!/usr/bin/env python
'''
Runs a method recursively, until SIGN_COLOR is "RED".
'''

from configparser import ConfigParser
from datetime import date, datetime
import time

constants = ConfigParser()
constants.read('traffic_light.ini')

counter = 1
current_color = constants.get('CONSTANTS', 'SIGN_COLOR') 

def recursion(*args, **kwargs):
    with open('timecount.html', 'a') as html_output:
        html_output.write(
            f'#{"{:08d}".format(counter)} | {date.today()} | <b>{datetime.now().strf>
        )
    time.sleep(1)


while current_color != 'RED':
    recursion()
    counter += 1

with open('timecount.html', 'a') as html_output:
    html_output.write('<p><font color="red">Ending cycle from signal "RED".</font></>
Content of traffic_light.ini:
; traffic_light.ini

[CONSTANTS]
SIGN_COLOR="GREEN"
On the host machine (Pycharm IDE) I run the script, the while loop goes on, then whenever I externally change the constant it will exit the loop and behave as expected.
On the server (SSH connection), it just never exits the while loop.

Any idea of why this would happen?
I tried different ways to refactor my code but anything seems to work.
Look if 'traffic_light.ini' are locally and on the server are identical.
(Jan-04-2023, 12:44 PM)DeaD_EyE Wrote: [ -> ]Look if 'traffic_light.ini' are locally and on the server are identical.

Did double check that, they are identical.
I also noticed by reading the docs that configparser does expect strings to be wrapped in commas, so I removed them in traffic_sign.ini.
Yet, still the same undesired behaviour.
It seems like the constant doesn't get updated during the while loop and stays the same than at the beginning, but I can't figure out why.
Update, I managed to debug this definitely.

Description of the error: when updating current_color from within the while loop, I forgot to PARSE again the .ini file, so it didn't update but stayed always the same.

Corrected code:
#!/usr/bin/env python
'''
Runs a method recursively, until status.txt reads "RED".
'''

from configparser import ConfigParser
from datetime import date, datetime
import time

constants = ConfigParser()
constants.read('traffic_light.ini')

counter = 1
current_color = constants.get('CONSTANTS', 'SIGN_COLOR')

def recursion(*args, **kwargs):
    with open('timecount.html', 'a') as html_output:
        html_output.write(
            f'#{"{:08d}".format(counter)} | {date.today()} | <b>{datetime.now().strft>
        )
    time.sleep(1)

while current_color != 'RED':
    recursion()
    counter += 1
    constants.read('traffic_light.ini')
    current_color = constants.get('CONSTANTS', 'SIGN_COLOR')

with open('timecount.html', 'a') as html_output:
    html_output.write('<p><font color="red">Ending cycle from signal "RED".</font></p>
(Jan-04-2023, 03:44 PM)gradlon93 Wrote: [ -> ]Description of the error: when updating current_color from within the while loop, I forgot to PARSE again the .ini file, so it didn't update but stayed always the same.

I didn't know that you also want to detect changes.
The configparser object does not have a mechanism to automatically detect changes and reading the file again.

I guess it's better if you put the whole configparser logic into one function.
I introduced some changes and modernized the code.

import time
from configparser import ConfigParser
from datetime import datetime as DateTime
from pathlib import Path

RED = "RED"
TIMECOUNT = Path("timecount.html")
CONFIG = Path("traffic_light.ini")


def get_sign_color(file=CONFIG):
    """
    Return SIGN_COLOR from configuration
    By default, the Path CONFIG is used.
    """
    constants = ConfigParser()
    constants.read(file)
    return constants.get("CONSTANTS", "SIGN_COLOR")


def write_html(counter):
    with TIMECOUNT.open("a") as html_output:
        now = DateTime.now()

        today = now.date()
        hhmmss = now.time().replace(microsecond=0)

        output = f'#"{counter:08d}" | {today} | <b>{hhmmss}</b>\n'
        #"00000010" | 2023-01-05 | <b>11:24:28</b>\n
        html_output.write(output)

    time.sleep(1)


def main():
    counter = 1

    while get_sign_color() != RED:
        write_html(counter)
        counter += 1

    with TIMECOUNT.open("a") as html_output:
        html_output.write(
            '<p><font color="red">Ending cycle from signal "RED".</font></p>\n'
        )


if __name__ == "__main__":
    main()