Skript aus thread heraus beenden
Kleiner Nachtrag:
1. Mir ist aufgefallen, dass wenn ich mein Skript über einen watchdog bzw. generell im Hintergrund starte, das Skript zwar beendet wird, allerdings nicht in die Befehlszeile der Konsole zurückgekehrt wird. Bzw. Vielleicht läuft es sogar noch, ist nicht zu erkennen. Woran liegt das und wie kann ich es beheben?
2. Ist zwar etwas OT aber bevor ich schon wieder n neuen Thread starte ... In meinem Skript wird eine Email verschickt, dieser Vorgang spielt sich irgendwie jedes mal in meiner Konsole ab. Das will ich aber nicht, wie behebe ich auch das?
1. Mir ist aufgefallen, dass wenn ich mein Skript über einen watchdog bzw. generell im Hintergrund starte, das Skript zwar beendet wird, allerdings nicht in die Befehlszeile der Konsole zurückgekehrt wird. Bzw. Vielleicht läuft es sogar noch, ist nicht zu erkennen. Woran liegt das und wie kann ich es beheben?
2. Ist zwar etwas OT aber bevor ich schon wieder n neuen Thread starte ... In meinem Skript wird eine Email verschickt, dieser Vorgang spielt sich irgendwie jedes mal in meiner Konsole ab. Das will ich aber nicht, wie behebe ich auch das?
Code: Alles auswählen
import smtplib
import os
import signal
import MySQLdb as db
from contextlib import closing
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
def send_email(content, mysql_error_code):
fromaddr = ""
toaddr = ""
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "MySQL Error: " + mysql_error_code
msg.attach(MIMEText(content))
text = msg.as_string()
server = smtplib.SMTP('', 25)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.login('','')
server.sendmail(fromaddr, toaddr, text)
server.quit()
def kill_script():
pid = os.getpid()
os.kill(pid, signal.SIGKILL)
def insert_into_database(timestamp, datum, uhrzeit, energy_cam_value):
try:
with closing(
db.connect(
host='',
user='',
passwd='',
db='')
) as connection:
connection.cursor().execute(
'INSERT INTO EC_Zaehler_01(Zeitstempel, Datum, Zeit, Value) VALUES (%s, %s, %s, %s)',
(timestamp, datum, uhrzeit, energy_cam_value)
)
connection.commit()
except db.Error, e:
mysql_error_code = str(e.args[0])
mysql_error_message = str(e.args[1])
content = "Am " + datum + " ist um " + uhrzeit + " ein Fehler aufgetreten. \nEs konnte keine Verbindung zum Server hergestellt werden. \n\nFehlermeldung:\n" + mysql_error_message
send_email(content, mysql_error_code)
kill_script()
def main():
insert_into_database("123456789", "01:01:1990", "00:00:00", "100")
if __name__ == '__main__':
main()-
BlackJack
@mobby: Ad 1.: Wenn Du ein Programm generell im Hintergrund startest, bekommst Du *sofort* die Befehlszeile der Konsole, sonst ist es nicht im Hintergrund gestartet.
Ansonsten ist die Frage ob Deine Threads denn alle Daemon-Threads sind oder sich selbst beenden. Denn sonst endet das Programm erst wenn alle Threads beendet sind, also sich selbst beendet haben.
Ad 2.: Geh mal jede einzelne Zeile durch und mach Dir klar was die bewirkt. Dann findest Du die Stelle die offensichtlich dafür sorgt, dass der Vorgang sich in der Konsole ”abspielt”.
Ansonsten ist die Frage ob Deine Threads denn alle Daemon-Threads sind oder sich selbst beenden. Denn sonst endet das Programm erst wenn alle Threads beendet sind, also sich selbst beendet haben.
Ad 2.: Geh mal jede einzelne Zeile durch und mach Dir klar was die bewirkt. Dann findest Du die Stelle die offensichtlich dafür sorgt, dass der Vorgang sich in der Konsole ”abspielt”.
@BlackJack: Das ist richtig, ich starte das Skript im Hintergrund und ich bin sofort wieder in der Befehlszeile. Ich glaube ich löse zuerst mein Email Problem. Dank deinem Hinweis gehe ich mal davon aus, dass folgende Zeilen für den "print" verantwortlich sind:
Nur was muss ich machen, damit keine Konsolenausgabe passiert?
Code: Alles auswählen
server = smtplib.SMTP('', 25)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.login('','')
server.sendmail(fromaddr, toaddr, text)
server.quit()-
BlackJack
@mobby: Was machen denn die einzelnen Zeilen. Du musst Dir bei jeder doch etwas gedacht haben.
@BlackJack: öh *hust* okay, schon etwas peinlich.
SMTP.set_debuglevel(level):
Set the debug output level. A true value for level results in debug messages for connection and for all messages sent to and received from the server.
Lasse ich das weg, gibt es auch keine Konsolenausgabe
. Danke, dass du mir da die Augen geöffnet hast.
Und damit hat sich auch das Problem Nr. 1 gelöst, jetzt funktioniert alles mit dem Hintergrund-Prozess.
SMTP.set_debuglevel(level):
Set the debug output level. A true value for level results in debug messages for connection and for all messages sent to and received from the server.
Lasse ich das weg, gibt es auch keine Konsolenausgabe
Und damit hat sich auch das Problem Nr. 1 gelöst, jetzt funktioniert alles mit dem Hintergrund-Prozess.
Das mit dem subprocess hat mich nicht losgelassen und ich habe mich nochmals damit beschäftigt. Ich hoffe, dass ich jetzt auf dem richtigen Weg bin, kann aber die Variable nicht übergeben:
Mir ist bewusst, dass es sich ab dem 2. Listenelement um Argumente des Programms "kill" handelt. Und als zweites Argument erwartet kill eben die PID, nur wie bekomme ich das umgesetzt, wenn ich die PID vorher in einer Variable habe?
Auch beim Ermitteln der PID bin ich weiter:Passt so oder?
Code: Alles auswählen
import os
import subprocess
pid = str(os.getpid())
subprocess.Popen(["/bin/kill", "-SIGTERM", pid])Auch beim Ermitteln der PID bin ich weiter:
Code: Alles auswählen
import subprocess
pid = subprocess.check_output(["pidof", "-s", "python", "scriptname"])Code: Alles auswählen
import subprocess
pid = subprocess.check_output(["pidof", "-s", "python", "check.py"])
print pid
subprocess.Popen(["/bin/kill", "-15", pid])3099
kill: failed to parse argument: '3099
'
-
BlackJack
@mobby: Ah, da ermittelst Du die PID aber anders als im vorher gezeigten Code. Schau mal wo das schliessende ' bei der Ausgabe der PID in der Fehlermeldung steht, dann fällt Dir das Problem vielleicht auf. 
Code: Alles auswählen
import subprocess
pid = str.split(subprocess.check_output(["pidof", "-s", "python", "script.py"]))
print pid[0]
subprocess.Popen(["/bin/kill", "-15", pid[0]])
@mobby: wenn Du eigentlich ein strip willst, solltest Du das nicht mit split nachbauen.
Nur zur Vollständigkeit: kill ist keine Lösung des Problems, sondern ein Herumdoktorn an den Symptomen (ala, ich hab Kopfweh, also Kopf ab). Lösung ist ein Signalmechanismus an den Hauptthread und geordnetes Beenden des Programms.
Nur zur Vollständigkeit: kill ist keine Lösung des Problems, sondern ein Herumdoktorn an den Symptomen (ala, ich hab Kopfweh, also Kopf ab). Lösung ist ein Signalmechanismus an den Hauptthread und geordnetes Beenden des Programms.
@Sirius3: Das mit dem strip würde dann so aussehen: Läuft auf jeden Fall.
Um die Vervollständigung aufzugreifen, was verstehst du denn unter "geordnetes Beenden des Programms"? Und wie kann ich das umsetzen? In meiner Vorstellung ist lässt sich irgendwie schlecht einordnen, wie ich aus dem Thread heraus etwas an den Hauptprozess zurückgeben kann, was dann dort eine "Reaktion" auslöst.
Code: Alles auswählen
import subprocess
pid= subprocess.check_output(["pidof", "-s", "python", "script.py"])
print pid.strip()
subprocess.Popen(["kill", "-15", pid.strip()])Um die Vervollständigung aufzugreifen, was verstehst du denn unter "geordnetes Beenden des Programms"? Und wie kann ich das umsetzen? In meiner Vorstellung ist lässt sich irgendwie schlecht einordnen, wie ich aus dem Thread heraus etwas an den Hauptprozess zurückgeben kann, was dann dort eine "Reaktion" auslöst.
-
BlackJack
@mobby: Üblicherweise hat man im Hauptthread nur die Steuerung die mit den gestarteten Threads zum Beispiel über eine Queue kommuniziert. Wobei bei dem Beispiel das vielleicht noch nicht einmal nötig ist. Wenn der Thread der Werte in die Datenbank einträgt der einzige ist der das Programm beenden können soll, dann macht man diesen Teil einfach zu Hauptthread. Wenn es dann noch okay ist wenn die anderen Threads zum Programmende einfach so mitten drin ohne Aufräumarbeiten aufhören können, dann macht man die zu Daemon-Threads und lässt das Programm ganz einfach enden wenn das Eintragen in die DB nicht klappt.
