Script ab Schleife in den Hintergrund (Console)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bosko
User
Beiträge: 3
Registriert: Freitag 2. Mai 2025, 09:26

Hallo zusammen,

ich bin neu hier und auch neu in Thema Python aber Erfahrung in PHP und BASH.
Aktuell Programmiere ich ausschließlich Consolen Scripte (Linux).

Hier meine Frage, einfach Dargestellt.

In meiner Funktion, kommt der Befehl Print und ab da soll das Script als
Process in den Hintergrund und alles was danach kommt, läuft als Deamon.

Wie bewerkstellige ich dies oder gibt es wo Beispiele....

Gruß
Benutzeravatar
sparrow
User
Beiträge: 4522
Registriert: Freitag 17. April 2009, 10:28

Das wäre eher ungewöhnlich.
Statt "print" mit "logging" entsprechend in eine Datei loggen und den Daemon entsprechend als unit in systemd konfigurieren.
bosko
User
Beiträge: 3
Registriert: Freitag 2. Mai 2025, 09:26

Danke für die Antwort, vielleicht war meine Frage zu Kurz,

Nach dem Start des Script's, werden einige Daten Abgefragt, nach Beendigung der Eingabe, soll das Script in den Hintergrund Verschwinden
und als Prozess weiterlaufen.....
Benutzeravatar
sparrow
User
Beiträge: 4522
Registriert: Freitag 17. April 2009, 10:28

Das bleibt weiter eher ungewöhnlich.

Ein Daemon erwartet in der Regel keine Eingabe und erfordert auch keine Ausgabe - also keine Interaktivität.
Ausgaben werden in eine Log-Datei geschrieben, Eingaben normalerweise aus Konfigurationsdateien gelesen.
Dein interaktives Programm (will Eingaben, kommunziert mit dem Benutzer) könnte zum Beispiel diese Konfigurationsdatei schreiben und den Daemon fernsteuern (neustarten, Konfig neu einlesen, etc.)
Systemd-Units können auch für einen Benutzer konfiguriert werden. Das hat den Vorteil, dass man auch gleich konfigurieren kann, was bei einem Crash passieren soll, etc.

Den Python-Prozess _innerhalb_ des Scripts vom Parent zu lösen ist eher ungewöhnlich und fehleranfällig.

Es ist auch nicht ungewöhnlich, ein Script im Terminal laufen zu lassen, so lange man es braucht.
Die Entwicklungsserver der Webframeworks machen das zum Beispiel so.

Soviel aus deinen dünnen Infos.

Vielleicht solltest du einmal das grundsätzliche Problem erklären, dass du versuchst zu lösen. Denn möglicherweise ist die Lösung, die du für richtig hälst, falsch.
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bosko: Stimme sparrow grundsätzlich zu, ausser das logging in der Regel bei Diensten oft auch einfach auf die Standard- oder Standardfehlerausgabe geht und von dort dann in eine Datei umgeleitet werden kann, was mit systemd ja auch prima geht, dass das dann im Journal landet.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
bosko
User
Beiträge: 3
Registriert: Freitag 2. Mai 2025, 09:26

Hallo zusammen,

ich Poste mal mein Script, was ich umgeschrieben habe, was auch voll Funktionsfähig ist:

Code: Alles auswählen

import json, time, os

data = {}
PATH = './data.json'

if os.path.isfile(PATH) and os.access(PATH, os.R_OK):
    print("alles ok")
else:
    with open(PATH, "w") as f:
    	json.dump(data, f, indent=4)


def prozess():
	print("Hintergrundprozess ohne jegliche Ausgabe!!!!")


with open(PATH, 'r') as f:
    json_data = json.load(f)


def start_server():
	print("Server wurde gestartet...")
	time.sleep(1)
	##################################
	# Ab hier soll das Script in den
	# Hintergrund und die Funktion
	prozess()
	# Ausführen
	##################################


def conf_server():

	print("Enter your host:")
	HOST = input()
	print("Enter your port:")
	PORT = input()

	datas = {"conf": 1, "host": HOST, "port": PORT, "htdocs": "."}
	with open(PATH, "w", encoding="utf-8") as f:
		json.dump(datas, f, ensure_ascii=False, indent=4)
	print("Daten wurden geschrieben...")
	time.sleep(2)
	start_server() 

if "conf" in json_data:
	start_server()
else:
	conf_server()
es Handelt sich hier um ein Mini Web Server, sobald alle Eingaben gemacht sind und oder die json vorhanden ist.
soll das Srcipt ab der Funktion prozess() in den Hintergrund verschwinden und die WEB Funktion starten....
Benutzeravatar
sparrow
User
Beiträge: 4522
Registriert: Freitag 17. April 2009, 10:28

Ja, das betätigt in meinen Augen meine vorherigen Beiträge.

Und falls du dir da selbst irgend einen Webserver zusammenbastelst: Verwende die etablierten Frameworks wie Flask oder Django.
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
nezzcarth
User
Beiträge: 1739
Registriert: Samstag 16. April 2011, 12:47

bosko hat geschrieben: Freitag 2. Mai 2025, 20:46 Nach dem Start des Script's, werden einige Daten Abgefragt, nach Beendigung der Eingabe, soll das Script in den Hintergrund Verschwinden
und als Prozess weiterlaufen.....
Der Vollständigkeit halber: Einen echten Daemon-Prozess unter Unix zu erzeugen, ist mit traditionellen Methoden ein mehrstufiger Prozess, in dem der Prozess sich schrittweise mittels Double-Forking "freischält" (s.a.: https://www.freedesktop.org/software/sy ... %20Daemons). Wenn man das manuell umsetzen will, ist man mitten in der Welt der Unix-System-Programmierung und muss sich mit SysCalls, Signalen, ggf. sockets zum Kontrollieren, usw. relativ gut auskennen. Mal abgesehen davon, dass die Variante, wie du es umsetzen willst – dass das Programm interaktiv startet und dann in den Hintergrund geschoben wird – ein eher ungewöhnliches Design ist, ist es zudem heute viel üblicher, das unter Unix mit Systemd zu lösen, wie die anderen auch schon meinten. Auch von Paketen wie 'python-daemon' würde ich Abstand nehmen.
Antworten