ping test script.. Subprocess erkennt pinging nicht immer...

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

hallo miteinander..

Ich habe ein kleines Problem bei meiner Funktion. Diese ist dafür da, die Internet-Verbindung zu überprüfen anhand eines pings. "Jedoch merkt Subprocess nicht immer, dass ein Ping möglich ist", soll heissen meine Funktion liefert mir False, obwohl eine Internet Verbindung existiert. Dieses Problem habe ich nur sporadisch! Wenn aber, dann häuft es sich gleich 2,3 mal hintereinander...

Es sieht wie folgt aus:

Ich reboote mein Modem, mache eine kleine Pause, danach checkt meine Funktion (isConnectionAvailable()) ob ich wieder eine Internetverbindung habe. Diese Überprüfung läuft 5x in einer Schleife, jeweils mit einem wait von 10sec. Manchmal geschieht es nun, dass die isConnectionAvailable() Funktion sagt dass keine Verbindung möglich ist, danach wird das Modem erneut rebootet, pause, und wieder die isConnectionAvailable() Funktion (5x), dieses mal geht der check jedoch wieder problemlos...sprich bekomme ein True und alles ist gut.. :)
Das Lustige ist aber, wenn die isConnectionAvailable() Funktion ein paarmal False liefert nach dem 1. rebooten (eben die 5x versuche) und ich in dieser Zeit von Hand ein ping www.google.com mache in einer cmd, geht es auch nicht. ABER wenn ich in dieser Zeit den Firefox öffne, habe ich eine Verbindung zum Internet und gleich DANACH geht auch der ping check in der Funktion isConnectionAvailable()...
Daher meine Vermutung dass ich einen Fehler in meinem Subprocess habe, irgendwie bin ich wohl abgekappslet von der realen Systemwelt, bzw. bin "gefangen" im Sub process der nichts neues akzeptiert...brauche ich noch ein terminate()? system, etc. läuft alles unter python 2.5 leider... aber wie gesagt.. das Problem habe ich ja nicht immer...

Sorry für den langen text.. kanns nicht einfacher beschreiben.. :) hoffe ihr versteht mich...
danke für eure hilfe, tipps, ...

p.s. weiss das mein ping text find auf "Zielhost" nicht sauber ist, aber solch einen Fehler kann ich (bisher) nicht anders herausfinden...

system:
windows xp, sp2
python 2.5

code:

Code: Alles auswählen

def isConnectionAvailable():
    """
    @return: True if the internet connection is ok, otherwise False
    """
    returnBool = False  
    try:
        retval = subprocess.call('ping www.google.com', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if retval == 0:
            pipe = subprocess.Popen(('ping', 'www.google.com'), stdout=subprocess.PIPE)
            pingText = pipe.stdout.read()
            pipe.wait()
           
            if (pingText.find("Zielhost nicht erreichbar") > -1):
                returnBool = False
            else:
                returnBool = True
        else:
            returnBool = False
    except subprocess.CalledProcessError:
        returnBool = False
    except EnvironmentError, err:
        print "error while pinging:", err
        returnBool = False
     
    return returnBool
BlackJack

`subprocess.CalledProcessError` kannst Du gar nicht bekommen, das betrifft nur `subprocess.call_checked()`

Und laut Info's aus dem Netz ist der Rückgabewert von Windows' ``ping`` nichts Wert weil der auch bei einem Erfolg ungleich 0 sein kann. Es wird empfohlen nach der Zeichenkette 'TTL=' in der Ausgabe zu suchen. Ungetestet:

Code: Alles auswählen

def is_connection_available(remote_host='www.google.com'):
    pipe = subprocess.Popen(['ping', '-n', '1', remote_host],
                            stdout=subprocess.PIPE)
    ping_text = pipe.read()
    pipe.wait() # Ignore return code.
    pipe.close()
    return 'TTL=' in ping_text
Den `EnvironmentError` würde ich nicht so wie Du in der Funktion abhandeln. Da würde die Funktion `False` zurückgeben, wenn es zum Beispiel kein ``ping`` gibt. Das ist dann aber eventuell die falsche Antwort, denn das kein ``ping`` existiert, heisst ja nicht, dass keine Internetverbindung besteht.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Da BJ sich um die Funktion kümmerte, kümmer ich mich mal um den Code ;)
Du brauchst kein `returnBool'-Konstrukt, du kannst auch direkt return verwenden.
Außerdem solltest du dir mal PEP 8 anschauen.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du machst komische Dinge. Subprocess wird eigentlich eine Liste übergeben. Wie wär's so?

Code: Alles auswählen

import subprocess

def is_connected():
    try:
        subprocess.check_call(
            ['ping', '-c', '1', 'www.google.com'], 
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    except subprocess.CalledProcessError:
        return False
    return True
EDIT: Andere Beiträge nicht gelesen. Seite war schon länger offen...
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:Den `EnvironmentError` würde ich nicht so wie Du in der Funktion abhandeln. Da würde die Funktion `False` zurückgeben, wenn es zum Beispiel kein ``ping`` gibt. Das ist dann aber eventuell die falsche Antwort, denn das kein ``ping`` existiert, heisst ja nicht, dass keine Internetverbindung besteht.
Also wenn ich absichtlich nur "pin" eingebe (was es nicht gibt), erhalte ich einen OSError. Ändert natürlich trotzdem nicht daran, dass man da kein False zurückgeben sollte.
BlackJack

@snafu: Deine `is_connected()` funktioniert nicht, da der Rückgabecode von Windows' ``ping`` keine Bedeutung hat. Man kann daran nicht erkennen ob das ``ping`` erfolgreich war oder nicht.

Und `OSError` ist eine Unterklasse von `EnvironmentError`.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Deine `is_connected()` funktioniert nicht, da der Rückgabecode von Windows' ``ping`` keine Bedeutung hat. Man kann daran nicht erkennen ob das ``ping`` erfolgreich war oder nicht.
Wie gesagt. Ich las deinen Hinweis erst danach. Dann wird das Testen auf bestimmte Schlüsselworte wohl echt das Beste sein.
nepi
User
Beiträge: 23
Registriert: Montag 23. Juni 2008, 11:26

werde es sobald als möglich ausprobieren...

habt mir wieder mal super geholfen.. vielen dank & noch einen schönen abend euch..
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Es gibt auch verschiedene Skripte im Netz, die ping in Python implementieren. Das ist besser steuerbar, hat halt den Nachteil, dass es nur mit Admin-Rechten läuft.
lunar

mkallas hat geschrieben:Das ist besser steuerbar, hat halt den Nachteil, dass es nur mit Admin-Rechten läuft.
Unter Linux reicht CAP_NET_RAW und mit ctypes und libcap kann man die Rechte auch aufs Pingen beschränken.
nepi
User
Beiträge: 23
Registriert: Montag 23. Juni 2008, 11:26

habe nun dein code (blackjack) eingebaut...
jedoch noch 1 problem..

Code: Alles auswählen

def is_connection_available(remote_host='www.google.com'):
    pipe = subprocess.Popen(['ping', '-n', '1', remote_host],
                            stdout=subprocess.PIPE)
    ping_text = pipe.stdout.read()
    pipe.wait()
    return 'TTL=' in ping_text
Ich musste das

Code: Alles auswählen

pipe.close()
rausnehmen, da diese Methode laut Fehlermeldung nicht existiert auf diesem Objekt... (verwende python 2.5)

Code: Alles auswählen

AttributeError: 'Popen' object has no attribute 'close'


Wie kann ich sonst ein pipe/subprocess sauber terminieren/schliessen?
Ach ja beim read musste ich noch das stdout mitdazugeben...

vielen dank...
Antworten