@bosko: Anmerkungen zum Quelltext:
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Variablen haben da nichts zu suchen (`data`) und das Hauptprogramm zwischen Funktionsdefinitionen verteilt auch nicht. Das steht üblicherweise in einer Funktion die `main()` heisst.
Die gleiche Datenstruktur heisst in dem Programm mal `data`, `json_data`, oder `datas`. Letzteres ist falsch, weil die Mehrzahl von `data` auch `data` ist.
Solche Tests bevor man etwas mit Dateien macht, sind in der Regel falsch. Zwischen dem Test und der Aktion kann sich etwas an der Situation ändern und bei den Aktionen mit Dateien sind die Tests ja auch noch mal enthalten, denn die lösen dann Ausnahmen aus wenn man versucht beispielsweise ein Verzeichnis als Datei zu öffnen.
Die Reaktion auf ist keine Datei oder ist nicht zugreifbar ist auch nicht sinnvoll. Wenn das keine Datei ist, dann könnte es ein Verzeichnis sein und wenn man nicht drauf zugreifen darf, kann man es vielleicht auch nicht neu schreiben, dass heisst man läuft bei dem Versuch die Datei dann anzulegen Gefahr, dass das dann auch nicht funktioniert. Aber wie gesagt, man testet vorher sowieso nicht. Man macht einfach was man machen will, und reagiert entsprechend auf Fehler.
Es macht aber auch nicht wirklich Sinn eine leere Konfiguration zu speichern wenn die gleich danach wieder gelesen wird, um daraufhin zu entscheiden, dass die durch eine nicht-leere Konfiguration überschrieben wird.
Beim lesen der JSON-Datei wird keine Kodierung angegeben. Das sollte man machen, oder die Datei im Binärmodus öffnen, dann kümmert sich das `json`-Modul.
Namen sollten keine kryptischen Abkürzungen enthalten. Bei `conf_server` ist nicht klar ob es sich um einen `configuration_server` handelt oder um die Tätigkeit `configure_server`.
Das `conf_server()` nicht nur den Server konfiguriert, sondern auch noch startet ist unschön. Eine Funktion sollte nicht zu viel machen.
KOMPLETT_GROSS geschriebene Namen sind per Konvention Konstanten, dass heisst diese Schreibweise macht für lokale Namen keinen Sinn.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import json
CONFIG_FILE_PATH = "data.json"
def serve(configuration):
print("Hintergrundprozess ohne jegliche Ausgabe!")
def start_server(configuration):
print("Server wurde gestartet...")
#
# Ab hier soll das Script in den Hintergrund und die Funktion
serve(configuration)
# ausführen.
#
def configure_server():
print("Enter your host:")
host = input()
print("Enter your port:")
port = input()
configuration = {"conf": 1, "host": host, "port": port, "htdocs": "."}
with open(CONFIG_FILE_PATH, "w", encoding="utf-8") as file:
json.dump(configuration, file, ensure_ascii=False, indent=4)
print("Daten wurden geschrieben...")
return configuration
def main():
try:
with open(CONFIG_FILE_PATH, "rb") as file:
configuration = json.load(file)
except OSError:
configuration = {}
else:
print("alles ok")
if "conf" not in configuration:
configuration = configure_server()
start_server(configuration)
if __name__ == "__main__":
main()
Die Frage ist hier jetzt ob das mit dem leeren Wörterbuch und dem "conf"-Schlüssel tatsächlich so sein soll, oder ob man `configure_server()` nicht einfach im ``except``-Zweig aufrufen sollte.
Zur eigentlichen Frage: Nenn mal bitte Programme die das machen was Du willst. Ich kenne keine. Man macht das einfach nicht so, weil man dass Programm dann nicht mehr als Dienst verwenden kann. Denn wenn man das über die üblichen Wege als Dienst startet, bekommt man gar nicht mit, dass das Programm die Konfiguration nicht lesen konnte, und jetzt irgendwo auf Benutzereingaben wartet, die niemand geben kann.
Üblich ist, dass dein Dienst eine Konfigurationsdatei hat, und wenn dadurch nicht alle Daten zusammenkommen, mit einer Fehlermeldung abbricht. Wobei Konfigurationsdatei schon der zweite Schritt ist — in erster Linie gibt es Kommandozeilenargumente wenn nur so wenige Angaben gefragt sind. Und die haben in der Regel auch Default-Argumente. Statt so komische Sachen machen zu wollen, wäre also eher ein Hinweis auf `argparse` aus der Standardbibliothek oder `click` wenn es auch etwas externes sein darf, gefragt.