Seite 1 von 1

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

Verfasst: Mittwoch 18. Februar 2009, 18:06
von nepi
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

Verfasst: Mittwoch 18. Februar 2009, 18:49
von 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.

Verfasst: Mittwoch 18. Februar 2009, 19:02
von cofi
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.

Verfasst: Mittwoch 18. Februar 2009, 19:13
von snafu
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...

Verfasst: Mittwoch 18. Februar 2009, 19:19
von snafu
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.

Verfasst: Mittwoch 18. Februar 2009, 19:33
von 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`.

Verfasst: Mittwoch 18. Februar 2009, 19:38
von snafu
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.

Verfasst: Mittwoch 18. Februar 2009, 22:02
von nepi
werde es sobald als möglich ausprobieren...

habt mir wieder mal super geholfen.. vielen dank & noch einen schönen abend euch..

Verfasst: Freitag 20. Februar 2009, 15:12
von mkesper
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.

Verfasst: Freitag 20. Februar 2009, 15:50
von 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.

Verfasst: Montag 23. Februar 2009, 16:33
von nepi
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...