Ich betreibe mittels Rspberry eine LED-Matrixanzeige, die ihre Inhalte
per UDP entegen nimmt. Wenn eine Netzwerkverbindung besteht,
funktioniert Alles einwandfrei.
Zufällig habe ich festgestellt, dass mein Python-Programm sang- und
kalnglos beendet wird (Und die gesamte Anzeige dunkel bleibt), wenn
diese eingeschaltet wird, ohne dass eine Netzwerkverbindung besteht. Ich
hätte für den Fall aber gerne eine Anzeige wie z.B. "no network" oder so
ähnlich.
Natürlich wollte ich die Initialisierung des UDP-Socket per try/except
abfangen, funktioniert aber nicht. Ich habe eine Funktion "init()", in
der ich das proiert habe, wie gesagt, funktioniert nicht. Kann mal bitte
jemand drübersehen und mit sagen, warum nicht? Danke!
Idle(...) ist eine Funktion, die ein Testbild mit einer eingebetteten
Nachricht ausgibt, die funtioniert einwandfrei. Host und Port sind
globale Variablen, sock wird deshalb "globalisiert", weil weiter unten
Lese- und Schreiboperationen stattfinden. DAS läuft Alles einwandfrei,
es geht nur um des Problem "mit ohne Netzwerkinterface" ...
Frank E. schrieb:> Natürlich wollte ich die Initialisierung des UDP-Socket per try/except> abfangen, funktioniert aber nicht. Ich habe eine Funktion "init()", in> der ich das proiert habe, wie gesagt, funktioniert nicht. Kann mal bitte> jemand drübersehen und mit sagen, warum nicht? Danke!
Was sagt denn die Konsole? Nun, ich nehme an, Du betreibst das Teil ohne
Monitor und daher bei fehlendem Netz ohne Diagnosemöglichkeit. Ich löse
dergl. i.d. Regel so, daß ich den Output des Scripts in eine Datei
umleite und außerdem alles noch mal in einen try/except Exception,c:
Block klammere, falls ich im Falle einer unerwarteten Exception mehr als
einen bloßen Traceback haben möchte. Hauptziel ist, im Fehlerfall
genügend Diagnoseinformationen zu bekommen.
Mit lediglich dem obigen Schnipsel läßt sich mehr nicht sagen. Zwar ist
socket.error Oberklasse von allen Exceptions, die von socket selber
geworfen werden. Jedoch kann z.B., je nachdem, wie "host" zustandekommt,
socket durchaus auch andere Exceptions werfen, z.B. produziert
host="\x00" einen TypeError, der nicht abgefangen wird.
Ohne Netz oder bei jedem sonstigen Fehler in ein reboot-Schleife zu
gehen kommt mir auch nicht übermäßig klug vor. Der Pi ist ziemlich
empfindlich, was gewaltsames Abschalten in laufendem Betrieb angeht, und
anders kommst Du aus so etwas kaum raus. So lange nicht alles 100%ig
robust funktioniert, wäre hier das Produzieren von reichlich
Diagnoseoutput gefolgt von einem sauberen poweroff die bessere Lösung.
Wenn die IP, zu der host auflöst, (noch) nicht einem lokalen Interface
zugewiesen ist, scheitert bind(). Du brauchst IP_FREEBIND oder
einfacher, wenn nichts dagegen spricht, nimm als host INADDR_ANY.
Malte S. schrieb:> Wenn die IP, zu der host auflöst, (noch) nicht einem lokalen Interface> zugewiesen ist, scheitert bind().
Das ist richtig. Allerdings wirft das Scheitern einen socket.error, und
der wird abgefangen.
> Du brauchst IP_FREEBIND oder> einfacher, wenn nichts dagegen spricht, nimm als host INADDR_ANY.
Bleibt die Frage, ob das das gewünschte Verhalten ist.
Wolfgang S. schrieb:> Das ist richtig. Allerdings wirft das Scheitern einen socket.error, und> der wird abgefangen.
Richtig. Mir lag auch mehr daran, das Auftreten evtl. ungewollter Fehler
zu vermeiden.
> Bleibt die Frage, ob das das gewünschte Verhalten ist.
Auch im Sinne, das Skript robust zu kriegen im Falle oft transienter
Fehler. Zumal sich die Frage stellt, was "Netzwerk da?" bedeutet. Das
Vorhandensein einer bestimmten(?) lokalen IP hat noch relativ wenig mit
tatsächlich möglicher Kommunikation zu tun. Ebenso wie das derzeitige
Nichtvorhandensein von Netzwerkkonnektivität einen Daemon am Start oder
Weiterlaufen hindern sollte. Daher wenn sich das nicht aus Gründen
verbietet INADDR_ANY bind()en und ggFs. parallel regelmäßig z.B. durch
Ping (ICMP oder was unpriviligiertes) eines definierten Ziels die
Wahrscheinlichkeit des Erreichbarseins überprüfen.
Hallo, danke für die Antworten. Leider bin ich derzeit zu wenig Linux-
und Python-Experte, um da selber wirklich kreativ zu werden und die Zeit
drängt auch ein wenig.
Ich habe aber bei meinen Recherchen eine Funktion entdeckt, die mir für
mein konkretes Problem ausreichend weiterhilft. Ich weiss zwar nicht
genau, was die eigentlich wie tut (ist ja oft so bei fremdem Code), aber
sie liefert mir eine Liste der AKTIVEN Netzwerkinterfaces, die ich dann
entsprechend auswerten kann ("befindet sich eth0 in der Liste und hat es
eine passende IP"). Und wichtig: Sie schmiert nicht ab!
Wen es interessiert:
1
def interfaces():
2
is_64bits = sys.maxsize > 2**32
3
struct_size = 40 if is_64bits else 32
4
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Frank E. schrieb:> Und wichtig: Sie schmiert nicht ab!
Das glaube ich nicht. Die folgende Zeile kann gar nicht funktionieren.
> ifaces.append(iface_name,iface_addr)
Ansonsten ist es ja nett, eine Funktion zu haben, die die aktiven
Interfaces als Tupel aus Name und zugeordneter IP auflistet, indem sie,
unter Linux laufend, tief in die Eingeweide hineinschaut. Jedoch habe
ich den Eindruck, daß das zur Konfusion eher noch beiträgt. Aber ich
geb's auf. Wenn die Botschaft, daß man das plattformunabhängig
implementieren und testen kann, nicht ankommt, dann ist das eben so.