Warum nicht?veers hat geschrieben:Zum Glück ist signals keine globale Variable! *duck*
einfacher SMTP-Server
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo veers!veers hat geschrieben:Zum Glück ist signals keine globale Variable! *duck*
Es ist keine Variable die direkt über eine Funktion geändert wird. Geändert werden nur die Attribute *canceled* und *reload_it*. Und ja, ich pfeife auf Singletones. Man kann es ja auch übertreiben.

lg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hallo, Gerold!
Ich will hier ja keine Grundsatzdiskussion beginnen und schon gar nicht Dein Beispiel-Script angreifen. Aber rein "informativ" für einen "Nicht-Informatiker" wie mich:
1. Ich dachte, Klassen dienen dazu, Methoden und Attribute zu kapseln. Warum dann signal_handler als Funktion? Oder ist es üblich, Python-Klassen wie C-Structs allein zur Speicherung von Daten zu verwenden?
2. signals ist ja zumindest global, wenn vielleicht auch keine Variable. Ist das denn besser als canceled und reload_it gleich als globale Variablen zu verwenden?
MfG
HWK
Ich will hier ja keine Grundsatzdiskussion beginnen und schon gar nicht Dein Beispiel-Script angreifen. Aber rein "informativ" für einen "Nicht-Informatiker" wie mich:
1. Ich dachte, Klassen dienen dazu, Methoden und Attribute zu kapseln. Warum dann signal_handler als Funktion? Oder ist es üblich, Python-Klassen wie C-Structs allein zur Speicherung von Daten zu verwenden?
2. signals ist ja zumindest global, wenn vielleicht auch keine Variable. Ist das denn besser als canceled und reload_it gleich als globale Variablen zu verwenden?
MfG
HWK
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Nein, der Handler wäre besser in der Klasse aufgehoben wenn man konsequent OOP durchsetzen will. Siehe beim Beispiel, wo der Handler in der Klasse ist und nur Klassenvariablen modifiziert.HWK hat geschrieben:1. Ich dachte, Klassen dienen dazu, Methoden und Attribute zu kapseln. Warum dann signal_handler als Funktion? Oder ist es üblich, Python-Klassen wie C-Structs allein zur Speicherung von Daten zu verwenden?
Nein, globale Variablen sollte man vermeiden. Ich finde die `Signals`-Klasse auch sinnlos, da sie - wie du bereits sagtest - eigentlich ein Struct zu imitieren versucht. Da könnte man auch genauso gut ein Dict verwenden. Oder ein Dict, welches die Keys als Attribute bereit stellt, dann verhält es sich sogar genauso wie die Klasse `Signals`HWK hat geschrieben:2. signals ist ja zumindest global, wenn vielleicht auch keine Variable. Ist das denn besser als canceled und reload_it gleich als globale Variablen zu verwenden?

Oder man macht es einfach so wie ich es demonstiere, eine Klasseninstanz die alles lokal regelt und einen eigenen Signal-Handler hat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Will damit jetzt aber Gerolds Code nicht runtergemacht haben...
Bin jetzt aber eh gestraft, seitdem ich das Layout auf NEO-Layout gesetzt habe dauert jeder Satz eine halbe Ewigkeit. Hoffentlich zahlt sich das aus.
Bin jetzt aber eh gestraft, seitdem ich das Layout auf NEO-Layout gesetzt habe dauert jeder Satz eine halbe Ewigkeit. Hoffentlich zahlt sich das aus.

My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@Leonidas: Kleiner Bug in deinem Code?
Fehler:Leonidas hat geschrieben:Code: Alles auswählen
import signal, time class Listener(object): def complain(self, signum, frame): self.loop = False def run(self): signal.signal(signal.SIGHUP, self.complain) runs = 0 while True: runs += 1 print "Starting run %d" % runs self.loop = True while self.loop: time.sleep(1) Listener().run()
Laut help(signal) gibt es folgende Signale:Python hat geschrieben:Traceback (most recent call last):
File "server.py", line 17, in ?
Listener().run()
File "server.py", line 8, in run
signal.signal(signal.SIGHUP, self.complain)
AttributeError: 'module' object has no attribute 'SIGHUP'
Kann mir wer weiter helfen, denn ich finde kein SIGHUP?NSIG = 23
SIGABRT = 22
SIGBREAK = 21
SIGFPE = 8
SIGILL = 4
SIGINT = 2
SIGSEGV = 11
SIGTERM = 15
SIG_DFL = 0
SIG_IGN = 1
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Wenn du ein Modul `signal.py` nennst, ist es schon klar, dass es fehlschlägt.
In Gerolds Code ist es ebenso vorhanden und scheint dort zu funktionieren.
Bei mir jedenfalls ging es, ich musste es ja auch erstmal zum laufen bekommen. In Python 2.4 ist es auf jeden Fall definiert, es steht sogar als Beispiel in der Doku:

Bei mir jedenfalls ging es, ich musste es ja auch erstmal zum laufen bekommen. In Python 2.4 ist es auf jeden Fall definiert, es steht sogar als Beispiel in der Doku:
signal Dokumentation hat geschrieben:All the signal numbers are defined symbolically. For example, the hangup signal is defined as signal.SIGHUP; the variable names are identical to the names used in C programs, as found in <signal.h>.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo droptix!droptix hat geschrieben:Kann mir wer weiter helfen, denn ich finde kein SIGHUP?
Nicht jedes Betriebssystem kennt alle Signale. Windows kennt SIGHUP z.B. *nicht*.
Unter Linux hast du diese Signale zur Verfügung (SIG*):
Code: Alles auswählen
In [1]: import signal
In [2]: signal.
signal.NSIG signal.SIGPOLL signal.SIGUSR1 signal.__name__
signal.SIGABRT signal.SIGPROF signal.SIGUSR2 signal.__new__
signal.SIGALRM signal.SIGPWR signal.SIGVTALRM signal.__reduce__
signal.SIGBUS signal.SIGQUIT signal.SIGWINCH signal.__reduce_ex__
signal.SIGCHLD signal.SIGRTMAX signal.SIGXCPU signal.__repr__
signal.SIGCLD signal.SIGRTMIN signal.SIGXFSZ signal.__setattr__
signal.SIGCONT signal.SIGSEGV signal.SIG_DFL signal.__str__
signal.SIGFPE signal.SIGSTOP signal.SIG_IGN signal.alarm
signal.SIGHUP signal.SIGSYS signal.__class__ signal.default_int_handler
signal.SIGILL signal.SIGTERM signal.__delattr__ signal.getsignal
signal.SIGINT signal.SIGTRAP signal.__dict__ signal.pause
signal.SIGIO signal.SIGTSTP signal.__doc__ signal.signal
signal.SIGIOT signal.SIGTTIN signal.__getattribute__
signal.SIGKILL signal.SIGTTOU signal.__hash__
signal.SIGPIPE signal.SIGURG signal.__init__
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Und da liegt auch der Hund begraben, denn ich hab das unter Windows getestet. Dort spielt das ja auch nur eine Untergeordnete Rolle, da Services/Dienste völlig anders ablaufen.
Und wenn ich schon mal dabei bin: gibt es Scripts, um ein Python-Programm als Dienst zu installieren - wobei das Script selbst entscheidet unter welchem Betriebssystem welche Maßnahmen zu treffen sind? Also unter Unix über init-Script und unter Windows über die pywin32-Extensions?
Und wenn ich schon mal dabei bin: gibt es Scripts, um ein Python-Programm als Dienst zu installieren - wobei das Script selbst entscheidet unter welchem Betriebssystem welche Maßnahmen zu treffen sind? Also unter Unix über init-Script und unter Windows über die pywin32-Extensions?
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo droptix!droptix hat geschrieben:gibt es Scripts, um ein Python-Programm als Dienst zu installieren - wobei das Script selbst entscheidet unter welchem Betriebssystem welche Maßnahmen zu treffen sind? Also unter Unix über init-Script und unter Windows über die pywin32-Extensions?
Eher nicht. Denn unter Windows ist das sehr viele Schwieriger als unter Linux. Unter Linux reagierst du auf die zwei/drei Signale, kümmerst dich darum, dass beim Starten ein PID-File angelegt wird, beim Beenden das PID-File wieder gelöscht wird und legst ein Init-Skript an. Fertig!
Unter Windows ist das schon ein wenig komplizierter und meine persönliche Erfahrung damit ist, dass ein Dienst unter Windows sehr viel schwerer zu debuggen ist. Es kahm schon vor, dass ich Tage brauchte um einen Dienst für Windows so zu programmieren, dass dieser auch anstandslos auch unter den 40 verschiedenen Windows-Clients eines Kunden lief und sich auch schön mit Bordmitteln beenden und neu starten lies.
Zumindest bekommst du mit ``sys.platform`` raus auf welchem Betriebssystem dein Programm läuft. Dann kannst du dich selber um die Trennung kümmern.
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wer legt eigentlich das PID-File an -> mein Programm oder das Init-Script? Was steht da drin, ich nehme an einfach nur die Prozess-Id? Wo muss das PID-File liegen?gerold hat geschrieben:Unter Linux reagierst du auf die zwei/drei Signale, kümmerst dich darum, dass beim Starten ein PID-File angelegt wird, beim Beenden das PID-File wieder gelöscht wird und legst ein Init-Skript an. Fertig!
Stell ich mir nun wieder nicht so kompliziert vor... klar man weiß eigentlich gar nicht was Windows da macht, aber mit dem Tool "anysrv.exe" aus dem Windows Resource Kit hab ich meine Python-Scripts als Dienst zum Laufen bekommen, die sich dann auch regulär starten und beenden lassen.gerold hat geschrieben:Unter Windows ist das schon ein wenig komplizierter und meine persönliche Erfahrung damit ist, dass ein Dienst unter Windows sehr viel schwerer zu debuggen ist. Es kahm schon vor, dass ich Tage brauchte um einen Dienst für Windows so zu programmieren, dass dieser auch anstandslos auch unter den 40 verschiedenen Windows-Clients eines Kunden lief und sich auch schön mit Bordmitteln beenden und neu starten lies.
Nun ist das nicht gerade elegant, daher finde ich die pywin32-Geschichte sauberer und besser. Dort möchte ich mich reinfitzen...
Klaro, nur bevor ich da jetzt los lege wollte ich mal nachfragen, ob das nicht schon zufällig jemand vor mir realisiert hat.gerold hat geschrieben:Zumindest bekommst du mit ``sys.platform`` raus auf welchem Betriebssystem dein Programm läuft.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo droptix!
mfg
Gerold

Du musst das PID-File selber anlegen. Normalerweise in den Ordner */var/run/*. Drinnen sollte die Prozess-ID stehen.droptix hat geschrieben:Wer legt eigentlich das PID-File an -> mein Programm oder das Init-Script? Was steht da drin, ich nehme an einfach nur die Prozess-Id? Wo muss das PID-File liegen?
http://www.python-forum.de/topic-8422.html hast du sicher schon gelesen. Schwierig wird es erst bei größeren Programmen, die andere Module importieren sollen. Um Pfade und die kompletten Umgebungsvariablen musst du dich selber kümmern.droptix hat geschrieben:Nun ist das nicht gerade elegant, daher finde ich die pywin32-Geschichte sauberer und besser. Dort möchte ich mich reinfitzen...
mfg
Gerold

http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Theoretisch egal. DU kannst auch das Init-Skript und das Programm selbst zusammenlegen. Hat ja niemand behauptet, dass Init-Skripte in der `sh`-Sprache sein müssen. Praktisch hast du allerdings das Problem, wenn du im Init-Skript das PID-File anlegst dass das Programm sofort danach sterben kann (ImportError oder so), du also ein PID-File hast, dessen Prozess tot ist.droptix hat geschrieben:Wer legt eigentlich das PID-File an -> mein Programm oder das Init-Script? Was steht da drin, ich nehme an einfach nur die Prozess-Id? Wo muss das PID-File liegen?
FHS dazu.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Das passiert doch aber auch, wenn das Programm das PID-File anlegt und danach stirbt... es räumt ja keiner auf, richtig? Daher ist mir noch nicht klar, wie sich das vermeiden ließe...Leonidas hat geschrieben:Praktisch hast du allerdings das Problem, wenn du im Init-Skript das PID-File anlegst dass das Programm sofort danach sterben kann (ImportError oder so), du also ein PID-File hast, dessen Prozess tot ist.
Die Bashscripts fangen das dann ja auf und löschen den PID File, sollten sie zumindest.droptix hat geschrieben:Das passiert doch aber auch, wenn das Programm das PID-File anlegt und danach stirbt... es räumt ja keiner auf, richtig? Daher ist mir noch nicht klar, wie sich das vermeiden ließe...Leonidas hat geschrieben:Praktisch hast du allerdings das Problem, wenn du im Init-Skript das PID-File anlegst dass das Programm sofort danach sterben kann (ImportError oder so), du also ein PID-File hast, dessen Prozess tot ist.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Im Python hast du das Problem eigentlich gar nicht weil du mit `atexit` Funktionen definieren kannst die dann am Schluss aufräumen. Außer dein Programm crasht den Interpreter, aber das bekommst du eigentlich nur mit kaputten C-Modulen hin, ansonsten ist der Interpreter ziemlich robust.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice