Seite 1 von 2

Skript aus thread heraus beenden

Verfasst: Donnerstag 3. Juli 2014, 17:50
von mobby
Hey Leute,

ich stehe vor dem Problem, dass ich aus einem gestarten Thread heraus das gesamte Skript beenden möchte. Bisher habe ich mit Folgendem gearbeitet.

Code: Alles auswählen

import sys
sys.exit()
Da das ja im Haupt Prozess ausgeführt werden muss frag ich mich wie ich das aus dem Thread herraus anstelle :?

Thanks for feedback!

Gruß
mobby

Re: Skript aus thread heraus beenden

Verfasst: Donnerstag 3. Juli 2014, 18:42
von Sirius3
@mobby: Warum mußt Du denn das Programm aus einem Thread beenden?

Re: Skript aus thread heraus beenden

Verfasst: Donnerstag 3. Juli 2014, 19:49
von mobby
@Sirius3: In diesem Thread wird die Bedingung überprüft, die dazu führen kann, dass das Skript beendet werden muss. Die Überprüfung ist auch nicht auf den Haupt Prozess übertragbar.

Re: Skript aus thread heraus beenden

Verfasst: Donnerstag 3. Juli 2014, 22:12
von BlackJack
@mobby: Warum!?

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 10:20
von mobby
@BlackJack: Es geht immer noch um das gleiche Projekt, zu dem ich schon mehrere Threads im Forum gestarte habe, also Situation:

Haupt Prozess zählt konstant etwas. Im Thread wird alle x Sekunden eine Datenbankverbindung aufgebaut und die Ergebnisse des Haupt Prozesses in die DB übertragen. Bei diesem Verbindungsufbau wird, falls ein Fehler auftritt, eine Email an den System Administrator geschickt und das gesamte Skript soll beendet werden. Ja theoretisch könnte ich nur den fehlerhaften Thread schließen, aber ich fände es angenehmer zu wissen, dass alles aus ist.

Eine Möglichkeit die ich mir überlegt habe ist, dass beim Start des Skriptes die Prozess-ID ermittelt und diese in den Thread mit übergeben wird. Sollte dann der Fehler auftreten, könnte ich das gesamte Skript über die Prozess-ID killen. Nur jetzt die Frage, ob das nicht auch einfacher geht?

Ist das ein so außergewöhnlicher Vorgang? Wenn ja, warum? ^^

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 10:34
von EyDu
mobby hat geschrieben:Ist das ein so außergewöhnlicher Vorgang? Wenn ja, warum? ^^
Nö, aber wahrscheinlich ist die Aufteilung deiner Threads etwas ungünstig. Der Hauptthread sollte sich eigentlich nur um die Verwaltung des Programms kümmern und die Aufgaben ggf. an andere Threads deligieren. Bei dir steckt im Hauptthread jedoch offenbar die ganze Logik. Daher würde ich aus dem Hauptthread einen Nebenthread machen, welcher ganz normal gestartet wird. Der Hauptthread kümmert sich dann nur um das Starten der Threads und nimmt anschließend Nachrichten von diesen entgegen.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 11:38
von mobby
@EyDu: Danke für den Hinweis, aber gehen wir jetzt mal davon aus, dass ich die Struktur nicht mehr abändern möchte. Daher mein Ansatz wie ich das lösen würde:

Code: Alles auswählen

import subprocess

process_id = subprocess.check_output(["ps aux | grep skriptname | awk '{ print $2 }'"], shell=True)
Dann übergebe ich die Variable an den Thread und falls meine Bedingung erfüllt wird kill ich das Skript.

Code: Alles auswählen

subprocess.call(["kill -9 " + process_id], shell=True)
Ohne shell=True funzt schon mal gar nix und jetzt kommen bei der Abfrage 4 PIDs raus ... ich möchte aber nur die aktuelle des laufenden Skriptes :cry: was mach ich falsch?

//edit: Zudem habe ich dabei ein Problem mit Rechten ... :(

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 12:09
von Sirius3
@mobby: das ist ja auch nicht der richtige Weg. Ein einfaches Flag, das vom Thread gesetzt wird und vom Hauptprogramm abgefragt wird, ist doch viel klarer und logischer, als dieses ganze Konstrukt, das Du da gerade zusammenschusterst.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 12:10
von snafu
Python nur dafür zu nutzen, Shell-Befehle auszuführen und deren Ergebnisse herumzureichen, ist keine wirkliche Python-Programmierung.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 12:16
von BlackJack
Zumal das gar nicht nötig ist, weil man das auch mit Python-Bordmitteln erreichen kann.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 12:21
von EyDu
mobby hat geschrieben:@EyDu: Danke für den Hinweis, aber gehen wir jetzt mal davon aus, dass ich die Struktur nicht mehr abändern möchte.
Warum willst du denn die Struktur deines Programms nicht mehr ändern? Wenn es halbwegs sauber programmiert ist, dann ist das doch eine total einfache Sache. Alles anderes ist doch nur eine Notlösung, welche dir früher oder später wohl um die Ohren fliegen wird.

Aber mal eine andere Sache: Du scheinst das subprocess-Modul nicht so richtig verstanden zu haben. Es gibt einen Grund, warum die ganzen Methoden als ersten Parameter eine Liste erwarten und warum der Wert des shell-Parameters per Default auf False gesetzt ist. Außerdem unterstüzt das subprocess-Modul ebenfalls Pipes, das solltest du alles nicht per Hand umsetzen. Lies dier doch besser noch einmal die Dokumentation dazu durch, du benutzt das Modul gerade so, wie es auf keinen Fall benutzt werden sollte. Um solche Dinge wie deine Aufrufe zu vermeiden wurde das subprocess-Modul überhaupt erst eingeführt.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 14:10
von mobby
Vielen Dank für die Rückmeldungen. Ich bin mir im klaren, dass ich da noch ziemlich viele Fehler mache und auch sicherlich einige Grundlagen fehlen. Ich bin dran das alles so langsam aufzuarbeiten. Da Python nur eine art Hobby von mir ist, habe ich leider nicht viel Zeit mich damit ausgiebig zu beschäftigen. Das hat dann solche Fails zur Folge ...

@Sirius3: Der Ansatz hört sich, so wie ich deine Aussage interpretiere, relativ einfach und logisch an. Nur wie mache ich das? Wenn ich nach Python und Flags suche, komme ich beim "argparse" Modul raus. Inwiefern ich das in meinem Beispiel anwenden kann, ist mir jedoch schleierhaft.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 14:31
von EyDu
mobby hat geschrieben:@Sirius3: Der Ansatz hört sich, so wie ich deine Aussage interpretiere, relativ einfach und logisch an. Nur wie mache ich das? Wenn ich nach Python und Flags suche, komme ich beim "argparse" Modul raus. Inwiefern ich das in meinem Beispiel anwenden kann, ist mir jedoch schleierhaft.
Das ist keine Alternative zu der von mir beschriebenen Lösung, sondern ein Weg diese umzusetzen. Die dazu nötigen Elemente findest du im threading-Modul, du solltest dir dazu wirklich dringend die Dokumentation durchlesen. Wenn du mit Threads arbeitest, dann musst du das können. Sonst schießt du dir ganz schnell selbst in den Fuß. Ansonsten ist das queue-Modul noch sehr nützlich.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 14:35
von mobby
Sorry for double post, aber ich hab mal was versucht:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from threading import Thread
from threading import Lock
from time import sleep


class Status_check(object):
    def __init__(self,value=False):
        self.value = value
        self.lock = Lock()

    def set_status_kill(self):
        with self.lock:
            self.value = True
            result = self.value
        return result


def test(status):
    print "Hallo ich bin der Thread"
    sleep(10)
    status.set_status_kill()


def start_thread(status):
    thread = Thread(target=test, args=(status))
    thread.setDaemon(True)
    thread.start()


def main():
    status = Status_check()
    start_thread(status)

    if status.set_status_kill() == True:
        sys.exit()

    while True:
        print "hallo ich bin der Hauptprozess"


if __name__ == '__main__':
    main()
Ist das von der Herangehensweise richtig oder lieg ich schon wieder voll daneben? Das es noch nicht funltioniert ist mir klar, denn wenn ich das ausprobiere killt er das Skript zwar, aber nicht zum gewünschten Zeitpunkt, sondern sofort KP warum ... lol

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 16:38
von snafu
Bevor man die Pipes mittels der ``subprocess``-API umsetzt, kann man auch gleich die Anwendung von ``grep`` und ``awk`` mit Python-Mitteln ersetzen. Dann bleibt nur noch ``ps aux`` übrig. Rein theoretisch könnte man selbst dafür eine Lib einsetzen, falls es ein entsprechendes Python-Package gibt. Aber da würde ich auch verstehen, wenn man einfach bei dem ``subprocess``-Aufruf bleiben möchte.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 17:08
von BlackJack
@snafu: Der ganze Aufruf mit der Pipe ist Unsinn weil es dafür eine Funktion in der Standardbibliothek gibt, die nicht nur deutlich robuster funktioniert weil sie einfach die entsprechende POSIX C-Funktion aufruft um die eigene PID zu ermitteln, sondern auch auf System wo es ``ps``, ``grep``, oder ``awk`` nicht gibt. Das was da Prozess-ID genannt wird kann letztendlich deutlich mehr sein weil ``ps aux`` (zumindest unter Linux) auch die Kommandozeilenargumente zu jedem Prozess ausgibt, und das ``grep`` *alles* findet wo 'skriptname' in der Zeile enthalten ist. Unter anderen auch *sich selbst*. m)

Code: Alles auswählen

$ ps aux | grep forum5.py | awk '{ print $2 }'
5928
5937
$ ps aux | grep forum5.py 
bj        5928  0.1  0.2  30268 11788 pts/5    Sl+  17:57   0:00 python forum5.py
bj        5940  0.0  0.0   4388   816 pts/6    S+   17:57   0:00 grep --color=auto forum5.py
Das ist, äh, suboptimal. ;-) Typischer Shell-Skripting-Hack den man öfter sieht, ist da noch ein ``| grep -v grep`` hinten dran zu hängen. Dann muss man aber sicher sein das das in der Zeile die man erwischen möchte garantiert nicht vorkommt, weder als Teilzeichenkette im Namen selbst, noch irgendwo in den Kommandozeilenargumenten.

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 21:36
von mobby
Ich löse mein Probelm jetzt einfach ruppig, indem ich einfach im Thread folgendes mache:

Code: Alles auswählen

pid = str(os.getpid())
subprocess.call(["kill -9 " + pid], shell=True)
Funktioniert ...

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 21:44
von BlackJack
@mobby: Wo Du doch Zeile 1 schon ohne `subprocess` hast, könntest Du das mit Zeile 2 vielleicht auch machen…

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 22:03
von mobby
@BlackJack: So besser?

Code: Alles auswählen

import os
import signal

pid = os.getpid()
os.kill(pid, signal.SIGKILL)

Re: Skript aus thread heraus beenden

Verfasst: Freitag 4. Juli 2014, 23:31
von jerch
@mobby:
Willst Du ernsthaft den Kontrollfluß über den Kernel steuern? Also ich ruf nicht beim Hausmeister an, ob er mal kurz den Strom abstellen könnte, nur weil die Waschmaschine noch an ist. :wink: