Seite 1 von 1

Service wird nicht beendet

Verfasst: Mittwoch 6. Oktober 2021, 16:43
von Bio Salami
Hi,
ich möchte einen service mit einem Python script starten und wieder beenden können. Leider komme ich nicht weiter. Hier mein Aktueller Code:

Code: Alles auswählen

import threading, os

class nodered(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    
    def run(self):
        os.system("node-red")
    
    def kill(self):
        exit()


nodeRed = nodered()
nodeRed.start()
_ = input("Stop")
nodeRed.kill()
Ich dachte das ich den service in einem zweiten Thread laufen lassen kann und dann mit der kill Methode wieder beenden.

Re: Service wird nicht beendet

Verfasst: Mittwoch 6. Oktober 2021, 16:59
von __deets__
Threads haben damit nichts zu tun. node-red ist ein eigener Prozess, ob du 1 oder 1000 Threads hast, das hat keinerlei Einfluss auf den.

Nimm subprocess.run, und darauf kannst du dann auch kill aufrufen.

Aber *warum*? Solche Dinge liefert dir dein Betriebssystem doch mit, warum bastelst du dein eigenes Prozessmanagement?

Re: Service wird nicht beendet

Verfasst: Mittwoch 6. Oktober 2021, 17:06
von Sirius3
Benutze subprocess.Popen (subprocess.run wartet bis der Prozess beendet wird), das kennt eine kill-Methode, Du brauchst keinen Thread!
Aber warum richtest Du node-red nicht als Service ein und benutzt die üblichen systemd-Mechanismen.

Re: Service wird nicht beendet

Verfasst: Mittwoch 6. Oktober 2021, 17:40
von __blackjack__
@Bio Salami: Beim letzten Thema wurde doch schon gesagt, dass man `os.system()` nicht verwendet, sondern das `subprocess`-Modul zum Starten von externen Programmen verwendet wird.

Klassennanmen werden als PascalCase geschrieben, damit man Klassen als solche schon am Namen erkennen kann. Normale Variablen werden per Konvention klein_mit_unterstrichen geschrieben.

`exit()` gibt es so eigentlich gar nicht, das ist eine Funktion die für den interaktiven Interpreter da ist. Wenn man ein Programm beenden will, dann nimmt man `sys.exit()`. Allerdings auch nur, wenn man zumindest potentiell etwas anderes als die implizite 0 als Rückgabecode an den Aufrufer übermitteln will. Ansonsten lässt man das Programm einfach ganz normal enden in dem halt keine Anweisungen mehr am Ende kommen und der Programmfluss am Ende vom Modul ankommt, und es so auf ganz ”natürliche” Art zuende ist.

Die `kill()`-Methode macht auch keinen Sinn, denn die wird ja vom Hauptthread aufgerufen, und *da* wirkt sich dann auch der `exit()`-Aufruf aus. Der beendet nicht den Thread, nur weil das in der Klasse steht.

Wenn es die `kill()`-Methode nicht mehr gibt und die Klasse nur noch aus der `__init__()` und `run()` besteht, braucht man die Klasse auch nicht. Dann kann man die Funktion die asynchron ausgeführt werden soll, auch über `Thread` und dessen `target`-Argument laufen lassen.

Das Originalprogramm macht letztlich genau das gleiche wie diese, um unnötigen Code der nichts weiter bewirkt, befreite Variante:

Code: Alles auswählen

#!/usr/bin/env python3
import os
from threading import Thread


def main():
    Thread(target=os.system, args=["node-red"]).start()
    input("Stop")


if __name__ == "__main__":
    main()
`Thread` braucht man aber gar nicht, weil man mit dem `subprocess`-Modul externe Prozesse auch nicht blockierend starten kann:

Code: Alles auswählen

#!/usr/bin/env python3
import subprocess


def main():
    with subprocess.Popen(["node-red"]) as node_red:
        input("Stop")
        node_red.terminate()


if __name__ == "__main__":
    main()
Edit: Ich wünschte die Leute würden nicht immer `kill()` empfehlen, weil das tatsächlich so gemeint ist — das sendet ein SIGKILL! Vielleicht ist das ``kill``-Unix-Kommando schuld, denn das sendet trotz des Namens per Default ein SIGTERM.