Prüfen ob Internetverbindung vorhanen ist

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nepi
User
Beiträge: 23
Registriert: Montag 23. Juni 2008, 11:26

Hi zusammen..

und wieder einmal nutze ich euer wissen gnadenlos aus.. :)

Ich habe mir eine Methode gebastelt, die anhand eines Pings testet, ob eine aktive Internetleitung vorhanden ist auf dem Rechner. Ich denke, mit einem Ping geht dies am schnellsten, andere Ideen??

Nun, mein 1 Versuch war dieser:

Code: Alles auswählen

def isConnectionOk():
    try:
        ret = call("ping www.google.com -n 2", stdout=-1, shell=True)
        if (ret):
            return 0
        else:
            return 1
    except:
        print "isConnectionOk: couldn't check internet connection"
        return 0 
Problem: Manchmal, wenn das Modem noch am resetten ist, schlug diese Methode fehl, sprich gab mir eine 1 zurück, obwohl noch *keine* Verbindung vorhanden war.

2. Versuch war:

Code: Alles auswählen

def isConnectionOk():
    pipe = Popen(('ping', 'www.google.ch'), stdout=PIPE)
    pingText = pipe.stdout.read()
    pipe.wait()
    
    if (pingText.find("Antwort von") > -1):
        return 1
    elif (pingText.find("Ping-Anforderung konnte Host") > -1):
        return 0
    else:
        return 0
Problem: Der stdout Text wird immer ausgegeben, egal was ich mache. Kann ich das verhindern? Möchte nicht in der console diesen output haben.
Sehe aber ein das ich den output des stdout brauche (-> pipe.stdout.read()). Aber vielleicht kann man den ja trotzdem abschalten?

vielen dank euch...
Zuletzt geändert von nepi am Mittwoch 16. Juli 2008, 16:21, insgesamt 1-mal geändert.
BlackJack

Auswertung des Rückgabecodes ist auf jeden Fall der Untersuchung des Textes vorzuziehen. Denn nicht jedes `ping` "antwortet" auf deutsch. Und selbst wenn man die Sprache kennt, kann sich der Text bei verschiedenen `ping`-Implementierungen unterscheiden.
nepi
User
Beiträge: 23
Registriert: Montag 23. Juni 2008, 11:26

aber wie stelle ich das in diesem Beispiel am besten an? Das 1. Codebeispiel war wie gesagt zu wenig genau, das hat mir aber immerhin rückgabecodes gegeben...
lunar

Der Rückgabewert eines erfolgreichen Kommandos ist 0, nicht 1 und "subprocess.call" gibt keine bool'schen Werte zurück! Dein Test im ersten Versuch ist also genau verkehrt herum. Dazu kommt noch, dass beim "shell=True" der Rückgabewert der Subshell zurückgegeben wird, der nicht notwendigerweise mit dem des aufgerufenen Kommandos identisch sein muss.

Richtig wäre folglich folgendes:

Code: Alles auswählen

retval = subprocess.call(['ping', '-n', '2', stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if retval == 0:
    print "google alive"
else:
    print "google dead"
Noch eleganter ist übrigens "check_call", welches eine Ausnahme auslöst, wenn der Rückgabewert nicht gleich 0 ist. Dadurch wird der Zweck imho deutlicher:

Code: Alles auswählen

try:
    subprocess.check_call(['ping', '-n', '2', stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
    print 'google alive'
except subprocess.CalledProcessError:
    print 'google dead'
except EnvironmentError, err:
    print 'error when pinging:', err
Noch ein paar generelle Anmerkungen zum Code.
Integer nicht als boolsche Konstanten missbrauchen (True und False existieren), keine magischen Nummern verwenden (statt "stdout=-1" "stdout=subprocess.PIPE"), "shell=True" nur einsetzen, wenn eine Shell gewünscht ist, niemals ein except ohne konkrete Ausnahme, dass den Traceback verschluckt, PEP 8 bei Namen einhalten!
nepi
User
Beiträge: 23
Registriert: Montag 23. Juni 2008, 11:26

super... vielen dank für deine hilfestellung!
werde die dinge gleich mal ausprobieren... habe in der zwischen zeit leider ein neues problem mit pickles... habe ein neuer thread aufgemacht...
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Warum nicht einfach mit [mod]urllib[/mod] eine Seite abrufen, statt ein externes ping zu verwenden. Mit dabei noch ein socket timeout z.B. auf 1 oder 2 setzten.

ping gibt's auch in Python, als externes Modul z.B.: http://trac.pylucid.net/browser/CodeSnippets/ping.py

Nachteil: Muß als root/Administrator laufen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
lunar

@nepi
Warum willst du eigentlich wissen, ob die Internetverbindung steht? In einer Anwendung ist das ziemlich unsinnig, weil man anstelle des Pings auch einfach gleich den Verbindungsaufbau versuchen kann. Sprich, anstelle vorher per ping zu gucken, ob Google lebt, und dann einen HTTP Request zu starten, kann ich den Request auch gleich abschicken. Das spart Traffic und öffnet vor allem keine Race Conditions.
jens hat geschrieben:Warum nicht einfach mit [mod]urllib[/mod] eine Seite abrufen, statt ein externes ping zu verwenden. Mit dabei noch ein socket timeout z.B. auf 1 oder 2 setzten.
Da würde ich lieber schnell was eigenes bauen, dass nur "HEAD" sendet. Man muss ja nicht zu viel Traffic verschwenden.

Code: Alles auswählen

from __future__ import with_statement
from contextlib import closing
import socket

def http_ping(server, port=80):
    try:
        with closing(socket.socket()) as sock:
            sock.settimeout(1)
            sock.connect((server, port))
            sock.send('HEAD / HTTP/1.0\r\n\r\n')
            return sock.recv(10).startswith('HTTP/1.0')
    except (socket.error, socket.gaierror, socket.timeout):
        return False
Um festzustellen, ob eine Internetverbindung besteht, reicht es aber eigentlich, einen beliebigen Port auf dem Zielhost abzufragen, und auf "socket.timeout" oder "socket.gaierror" zu reagieren. Diese Fehler signalisieren in der Regel ein Fehlschlagen des Verbindungsaufbaus. Ein "Connection refused" nämlich bedeutet ebenfalls, dass der Server lebt.

Der Vorteil an pings ist halt, dass man sie in schneller Folge senden kann, weil kein TCP-Handshake erforderlich ist, sondern nur ein Paket gesendet wird. Das ist in der Regel schneller als ein HTTP Ping.
Nachteil: Muß als root/Administrator laufen...
Unter Linux reicht CAP_NET_RAW, UID 0 ist nicht erforderlich.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich habe es glaube ich beim letzten Usertreffen erwähnt, dass wenn www.google.com irgendwann nicht auf Pings antwortet einige tausend Programme denken werden, dass sie offline sind.

Mich würde doch durchaus interessieren wie viele tausend ICMP Pings pro Tag bei Google aufschlagen um zu checken ob Google noch da ist, ahem, ob man online ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Gleiches gilt wohl für heise.de -- ich weiss jedenfalls, dass ich nicht der einzige bin, der die anpingt, um mal schnell manuell zu prüfen ob's Netz da ist. :-)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Hehe, die domains am-i-online.[com|org] waeren noch frei... :D
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

BlackJack hat geschrieben:Gleiches gilt wohl für heise.de -- ich weiss jedenfalls, dass ich nicht der einzige bin, der die anpingt, um mal schnell manuell zu prüfen ob's Netz da ist. :-)
Ist einfach kürzer als google.de ;)
BlackJack

Und man weiss ja auch nicht, was der Datenkrake Google mit den registrierten Pinganfragen macht. Vielleicht suchen die ja irgend wann einmal per Datamining nach Terroristen und ich habe zufällig ein auffälliges "Pingmuster". =:o)
lunar

Rebecca hat geschrieben:Hehe, die domains am-i-online.[com|org] waeren noch frei... :D
Eigentlich müsste man die registrieren und eine Seite ausliefern: "No!"
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

lunar hat geschrieben:
Rebecca hat geschrieben:Hehe, die domains am-i-online.[com|org] waeren noch frei... :D
Eigentlich müsste man die registrieren und eine Seite ausliefern: "No!"
Oder einfach Pings ignorieren ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten