Forum: PC-Programmierung Python 3: Uhr ohne Crash beenden


von Bernd W. (berndwiebus) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo

Im Anhang befindet sich das Python 3 Skript "UTC-Clock_RevA.py", welches 
unter Debian "funktioniert" und eine UTC-Uhr mit Datum darstellt.

Hauptproblem: Beim Drücken des Buttons "End" wird das Skript sehr 
unelegant
mit einem Crash beendet.

Vermutlich bekomme ich den Ärger wohl deshalb, weil der SIGALRM
auf einmal beim Beenden ins Leere läuft.
Wie beende ich nun den Timer, damit dass das nicht so passiert?

Mir ist sowieso etwas schleierhaft, was dort genau abläuft.
Auch die Informationen von http://docs.python.org/library/signal.html , 
woher ich mir das mit den Signalen zusammengeraten habe, erhellen mich 
nicht besonders.

Ausserdem würde mich interessieren, ob die Uhr auch unter Windows läuft.
Ich habe keinen Windows Rechner, aber vieleicht ist ja jemand so nett 
und testet mal.

Gibt es andere, bessere Konzepte, eine Uhr unter Python 3 zu betreiben?

Nebenproblem: Wenn ich aus der Importdeklaration am Anfang die Zeile 9 
"from tkinter.filedialog import *" entferne, weil ich im ganzen Skript 
keinen Filedialog habe, stürzt das Skript sofort ab. Auskommentieren der 
Zeilen 56 + 57:
"signal.setitimer(signal.ITIMER_REAL, 1, 1)" und
"signal.signal(signal.SIGALRM, ActualDate)"
führt dann zur Fehlermeldung:
Traceback (most recent call last):
  File "/home/wiebus/python/UTC-Clock_RevA.py", line 60, in <module>
    Rahmen1.pack(side = TOP, fill = X)
NameError: name 'TOP' is not defined
?????????


Vielen Dank im Voraus für Tipps und Hilfe.

mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

von Bernd W. (berndwiebus) Benutzerseite


Angehängte Dateien:

Lesenswert?

Nachtrag zu Beitrag #2849269:

> Im Anhang befindet sich das Python 3 Skript "UTC-Clock_RevA.py", welches
> unter Debian "funktioniert" und eine UTC-Uhr mit Datum darstellt.
>
> Hauptproblem: Beim Drücken des Buttons "End" wird das Skript sehr
> unelegant
> mit einem Crash beendet.

Dieses Problem ist mit der im Anhang befindlichen neuen Version 
"UTC-Clock_RevA2.py" behoben.
In Zeile 50 wurde in das "End" Unterprogramm
"signal.setitimer(signal.ITIMER_REAL, 0, 0)"
eingesetzt.
Das setzt den Timer auf 0, Was hier bedeutet, das er abgeschaltet ist, 
und beim Beenden nicht mehr stört.

> Mir ist sowieso etwas schleierhaft, was dort genau abläuft.
> Auch die Informationen von http://docs.python.org/library/signal.html ,
> woher ich mir das mit den Signalen zusammengeraten habe, erhellen mich
> nicht besonders.

Ok, ich hab gelesen und Begriffen, das Signale ein Problem für sich 
sind....komm ich aber vermutlich nicht drumrum.

>
> Ausserdem würde mich interessieren, ob die Uhr auch unter Windows läuft.
> Ich habe keinen Windows Rechner, aber vieleicht ist ja jemand so nett
> und testet mal.
>

Ist weiterhin eine aktuelle Fragestellung.

> Gibt es andere, bessere Konzepte, eine Uhr unter Python 3 zu betreiben?
>

Ist auch weiterhin eine aktuelle Fragestellung. Latenzzeiten von einem 
guten Dutzend Sekunden würde ich dabei durchaus aktzeptieren....so 
knallhart sind meine Anforderungen nicht.

> Nebenproblem: Wenn ich aus der Importdeklaration am Anfang die Zeile 9
> "from tkinter.filedialog import *" entferne, weil ich im ganzen Skript
> keinen Filedialog habe, stürzt das Skript sofort ab. Auskommentieren der
> Zeilen 56 + 57:
> "signal.setitimer(signal.ITIMER_REAL, 1, 1)" und
> "signal.signal(signal.SIGALRM, ActualDate)"
> führt dann zur Fehlermeldung:
> Traceback (most recent call last):
>   File "/home/wiebus/python/UTC-Clock_RevA.py", line 60, in <module>
>     Rahmen1.pack(side = TOP, fill = X)
> NameError: name 'TOP' is not defined
> ?????????
>

Ist wohl das Problem das ich schon einmal hatte: Namen sind in den 
Modulen wohl mehrfach vergeben, was zu Kollisionen führt.
So richtig Durchblicken tu ich da aber immer noch nicht.

Vielen Dank im Voraus für Tipps und Hilfe.

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

von Stefan L. (timpi)


Lesenswert?

Hallo Bernd,

Bernd Wiebus schrieb:
> Ist wohl das Problem das ich schon einmal hatte: Namen sind in den
> Modulen wohl mehrfach vergeben, was zu Kollisionen führt.
> So richtig Durchblicken tu ich da aber immer noch nicht.
>> Traceback (most recent call last):
>>   File "/home/wiebus/python/UTC-Clock_RevA.py", line 60, in <module>
>>     Rahmen1.pack(side = TOP, fill = X)
>> NameError: name 'TOP' is not defined

dann ersetze 'X', 'LEFT', 'RIGHT' und 'TOP' jeweils durch tkinter.X, 
tkinter.LEFT usw.
Oder sagen dem Script im Import-Teil woher es die Informationen nehmen 
soll nehmen soll:
1
from tkinter import X, LEFT, RIGHT, TOP

timpi

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

Bernd Wiebus schrieb:
> In Zeile 50 wurde in das "End" Unterprogramm
> "signal.setitimer(signal.ITIMER_REAL, 0, 0)"
> eingesetzt.

Der Timer sollte auch dann deaktiviert werden, wenn das Programm nicht
mit dem End-Button, sondern mit dem Close-Button des Window-Managers
oder Alt-F4 beendet wird. Das geht am einfachsten dadurch, dass beim
Schließen des Fensters end() aufgerufen wird:
1
Mainwindow.protocol("WM_DELETE_WINDOW", end)

Bernd Wiebus schrieb:
> Ausserdem würde mich interessieren, ob die Uhr auch unter Windows läuft.

Wahrscheinlich läuft sie nicht, weil lt. Anleitung setitimer nur für
Unix implementiert ist.

Ein generelles Problem (auch unter Linux) besteht darin, dass Tkinter
nicht threadsafe ist, weswegen der Aufruf von Tkinter-Funktionen aus dem
Signal-Handler zu Race-Conditions führen kann.

> Gibt es andere, bessere Konzepte, eine Uhr unter Python 3 zu
> betreiben?

Evtl. mit der after-Funktion von Tkinter (s. Anhang). Das kommt ohne
zusätzliche Signals und Threads aus, so dass sich keine Probleme mit
Race-Conditions ergeben. Außerdem ist sie nicht Unix-spezifisch, so dass
die Uhr gute Chancen hat, auch unter Windows zu laufen.

Da after immer nur ein Event erzeugt, muss es in ActualDate aufge-
rufen werden, um eine periodische Folge von Events zu erhalten. Dadurch
werden die einzelnen Zeitintervalle leider etwas länger als eine
Sekunde, so dass in gewissen Zeitabständen die Anzeige auch mal um 2s
statt 1s weiterspringen wird. Die Uhr läuft "runder", wenn man die
Zeitdauer zwischen zwei Events (erstes Argument von after) auf 200ms
verkürzt.

Die Anweisung
1
  Mainwindow.quit

ohne Klammern nach dem quit hat übrigens keinen Effekt. Du benötigst
diese Zeile aber auch gar nicht, da das davorstehende destroy des
Root-Fensters schon alles erledigt.

Wenn du das Datum als Ordinalzahl anzeigst (britisch), solltest du
Zahlen mit der Endzifffer 1 und 2 das "th" durch ein "st" bzw. "nd"
ersetzen wie hier

  http://stackoverflow.com/questions/5891555/display-the-date-like-may-5th-using-pythons-strftime

oder die Endung einfach komplett weglassen.

von Rolf Magnus (Gast)


Lesenswert?

Bernd Wiebus schrieb:
>> Ausserdem würde mich interessieren, ob die Uhr auch unter Windows läuft.
>> Ich habe keinen Windows Rechner, aber vieleicht ist ja jemand so nett
>> und testet mal.
>
> Ist weiterhin eine aktuelle Fragestellung.

Die Frage wird doch auf

Bernd Wiebus schrieb:
> http://docs.python.org/library/signal.html

recht eindeutig beantwortet:

"On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, 
SIGINT, SIGSEGV, or SIGTERM. A ValueError will be raised in any other 
case."

Yalu X. schrieb:
> Ein generelles Problem (auch unter Linux) besteht darin, dass Tkinter
> nicht threadsafe ist, weswegen der Aufruf von Tkinter-Funktionen aus dem
> Signal-Handler zu Race-Conditions führen kann.

Aus Signalhandlern heraus sollte man sowieso so wenig wie möglich 
machen. Einen Signalhandler kann man sich als eine Art user-space-ISR 
vorstellen, und die Regeln, die da gelten, sind ähnlich denen für ISRs.

von Bernd W. (berndwiebus) Benutzerseite


Lesenswert?

Hallo Stefan L., Yalu X. und Rolf Magnus.

Vielen Dank für die Hilfe, Tipps und Anregungen.

> dann ersetze 'X', 'LEFT', 'RIGHT' und 'TOP' jeweils durch tkinter.X,
> tkinter.LEFT usw.
> Oder sagen dem Script im Import-Teil woher es die Informationen nehmen
> soll nehmen soll:
> from tkinter import X, LEFT, RIGHT, TOP

Ich glaube, ich sollte mir die Module mal von innen ansehen, damit ich 
nicht immer mit den Namensräumen durcheinanderkomme.


> Der Timer sollte auch dann deaktiviert werden, wenn das Programm nicht
> mit dem End-Button, sondern mit dem Close-Button des Window-Managers
> oder Alt-F4 beendet wird. Das geht am einfachsten dadurch, dass beim
> Schließen des Fensters end() aufgerufen wird:
>
>
1
> Mainwindow.protocol("WM_DELETE_WINDOW", end)
2
>

Ok.


>> Ein generelles Problem (auch unter Linux) besteht darin, dass Tkinter
>> nicht threadsafe ist, weswegen der Aufruf von Tkinter-Funktionen aus dem
>> Signal-Handler zu Race-Conditions führen kann.
> Aus Signalhandlern heraus sollte man sowieso so wenig wie möglich
> machen. Einen Signalhandler kann man sich als eine Art user-space-ISR
> vorstellen, und die Regeln, die da gelten, sind ähnlich denen für ISRs.
>

Also besser meiden.

>> Gibt es andere, bessere Konzepte, eine Uhr unter Python 3 zu
>> betreiben?
> Evtl. mit der after-Funktion von Tkinter (s. Anhang). Das kommt ohne
> zusätzliche Signals und Threads aus, so dass sich keine Probleme mit
> Race-Conditions ergeben. Außerdem ist sie nicht Unix-spezifisch, so dass
> die Uhr gute Chancen hat, auch unter Windows zu laufen.

Ok, da bin ich dann mal gespannt.

>
> Da after immer nur ein Event erzeugt, muss es in ActualDate aufge-
> rufen werden, um eine periodische Folge von Events zu erhalten.

Ich spiele gerade etwas damit herum.

> Dadurch
> werden die einzelnen Zeitintervalle leider etwas länger als eine
> Sekunde, so dass in gewissen Zeitabständen die Anzeige auch mal um 2s
> statt 1s weiterspringen wird. Die Uhr läuft "runder", wenn man die
> Zeitdauer zwischen zwei Events (erstes Argument von after) auf 200ms
> verkürzt.

Ok. Für den Zeck hier ausreichend. ;O)

>
> Die Anweisung
>
1
>   Mainwindow.quit
2
>
>
> ohne Klammern nach dem quit hat übrigens keinen Effekt. Du benötigst
> diese Zeile aber auch gar nicht, da das davorstehende destroy des
> Root-Fensters schon alles erledigt.

Wofür wird dann " Mainwindow.quit()" verwendet? Bei reinen Interpreter 
Consolen Anwendungen ohne Fenster?


>
> Wenn du das Datum als Ordinalzahl anzeigst (britisch), solltest du
> Zahlen mit der Endzifffer 1 und 2 das "th" durch ein "st" bzw. "nd"
> ersetzen wie hier
~~~
> oder die Endung einfach komplett weglassen.


Dann lasse ich sie besser ganz weg.
Eigentlich hatte ich noch überlegt, eine Lokalisierung zu machen. Aber 
besser die nächsten 5 Jahre nicht.....anderes hat höhere Priorität auf 
der Python-todo Liste. ;O)

Mit freundlichem Gruß: Bernd Wiebus alias dl1eic
http://www.dl0dg.de

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.