Fehler bei http requests abfangen bei nicht existenter url

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
foto2004
User
Beiträge: 16
Registriert: Samstag 27. Juni 2020, 12:57

Hallo Gemeinde, wieder mal eine Anfänger Frage.

Ich habe mir folgenden Code zusammengestrickt und möchte wenn die Seite nicht erreichbar ist mir eine Mitteilung zusenden lassen.
Nun das mit der Mitteilung ist nicht das Problem sondern wen die Seite nicht erreichbar ist wird das Script nicht weiter ausgeführt weil natürlich die Seite nicht erreichbar ist.

Wie fange ich diesen Fehler ab? Das mit dem "except ValueError:" geht nicht ist mir schon klar aber was muss stattdessen dort hin?

Code: Alles auswählen

import requests
r = requests.get("https://www.XYZ.de/check.txt")


while True:
    try:
        print('Status Code:')
        print(r.status_code)
        print('Inhalt:')
        print(r.text)

        if (r.text != 'ok'):
            print('Ist nicht OK')
        else:
            print('Ist online')
        
        break
    
    except ValueError:

noch ganz am Anfang vom Lernen ...
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast doch einen Status Code. Den printest du sogar. Benutz den doch. Mit einem if.

Das try/except ist so im übrigen komplett sinnlos, weil wenn der request.get-Aufruf Fehlschlägt. Der ist aber davor.

Nachtrag: ich habe Unsinn geredet mit dem Status Code. Wenn die nicht erreichbar ist, wird eine Ausnahme ausgelöst. Aber dazu muss der Aufzug schon in das try. Und was auch immer dann fliegt, dass fängst du.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Das Verhalten hängt davon ab ob es die Domain 'https://www.XYZ.de' gibt oder nicht.
Wenn das nicht der Fall ist, gibt es einen ConnectionError, den man mit try / except behandeln kann. Das liegt daran, dass dem Domainnamen keine IP-Addresse zugeordnet werden kann.

Falls es die Domain 'https://www.XYZ.de' grundätzlich gibt und der Webserver so konfiguriert ist, dass er grundsätzlich auf requests an port 443 und / oder 80 antwortet, wird es keine Exception geben.
Statt dessen wird der Server mindestens mit einem Status-Code antworten.
Wenn ein url-pfad nicht vom Server aufgelöst werden kann (z.B.: 'https://www.XYZ.de/nicht_vorhanden'), wird der Server mit einem Status-Code 404 antworten.

Es gibt auch noch viele weitere Fehlermöglichkeiten, je nachdem ob der Server fehlerfrei arbeitet oder nicht.

Du musst dir also überlegen, welche Fehler du grundsätzlich erwartest.
foto2004
User
Beiträge: 16
Registriert: Samstag 27. Juni 2020, 12:57

Mir geht es nicht um die Statuscodes sondern rein darum ist der Server auf http erreichbar oder nicht. Namenauflösung und der gleichen passt alles.
Es geht nur Datum dass mir der Server öfters mal aussteigt und er wieder neu gestartet werden muss und ich es mitbekomme wann das ist.

ich erwarte eigentlich eine Fehler in der Art "nicht vorhanden"
noch ganz am Anfang vom Lernen ...
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aber den bekommst du doch. Dein eigener Code mit einer nicht-existenten (was so gut ist wie nicht erreichbaren) Domain spuckt das hier aus:

Code: Alles auswählen

>>> r = requests.get("https://www.gibt-es-nicht.de")
Traceback (most recent call last):
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connection.py", line 169, in _new_conn
    conn = connection.create_connection(
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/util/connection.py", line 96, in create_connection
    raise err
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/util/connection.py", line 86, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connectionpool.py", line 699, in urlopen
    httplib_response = self._make_request(
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connection.py", line 353, in connect
    conn = self._new_conn()
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connection.py", line 181, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPSConnection object at 0x7f9930541c70>: Failed to establish a new connection: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/adapters.py", line 439, in send
    resp = conn.urlopen(
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/connectionpool.py", line 755, in urlopen
    retries = retries.increment(
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/urllib3/util/retry.py", line 574, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.gibt-es-nicht.de', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f9930541c70>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/api.py", line 76, in get
    return request('get', url, params=params, **kwargs)
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "/home/deets/.virtualenvs/tmp-XVr6zr33/lib/python3.8/site-packages/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.gibt-es-nicht.de', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f9930541c70>: Failed to establish a new connection: [Errno 111] Connection refused'))
Da hast du doch alles, was du brauchst. Wie man Exceptions behandelt wird in jedem halbwegs brauchbaren Tutorial erwaehnt, das offizielle auf python.org ist mE das empfehlenswerteste. Und ganz generell ist in solchen kompliziert aussehenden Faellen die erste die relevante Ausnahme.
foto2004
User
Beiträge: 16
Registriert: Samstag 27. Juni 2020, 12:57

ok so ganz werde ich da nicht schlau daraus (muss ich noch lernen)

wenn ich mit:

Code: Alles auswählen

while True:
    try:
        r = requests.get("https://xyz.d") #absichtlich falsch
        print('Status Code:')
        print(r.status_code)
        print('Inhalt:')
        print(r.text)
        print(r)
        if (r.text != 'ok'):
            print('Ist nicht OK')
        else:
            print('Ist online')
        break
    
   
    except:
        print('Fehler')
        print('der Server ist nicht erreichbar')
        break
macht er das. OK ist ja schön aber eigentlich ja nicht Sinn einer konkreten Fehlerbehandlung .....

wenn ich aber:

Code: Alles auswählen

 except ConnectionRefusedError:
einsetze machts wieder nur Fehler.

Abe danke für den schups in die Richtung
noch ganz am Anfang vom Lernen ...
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

"machts wieder nur Fehler" ist leider wenig aussagekräftig. Welche Fehler treten auf?
Wenn es zu einem Fehler kommt, dann musst du genau den Abfangen.
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

Hier mal so als erster Ansatz:

Code: Alles auswählen

#!/usr/bin/env python3
import requests

def is_alive(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
    except requests.exceptions.RequestException as error:
        print(error)
        return False
    return True


def main():
    url = 'http://127.0.0.1:8080/python-test'
    if not is_alive(url):
        print(f'{url} is not available.')


if __name__ == '__main__':
    main()
Für den Produktiveinsatz würde ich jedoch eine echte Monitoringlösung nehmen.
foto2004
User
Beiträge: 16
Registriert: Samstag 27. Juni 2020, 12:57

Danke für die Hilfe. Ich habe ..... nein ich denke dass ich es jetzt einigermaßen verstanden habe

Dieses "requests.exceptions.ConnectionError:" Stand ja in der ganzen Fehlermeldung (xZeilen) ganz unten und ich denke dass das der relevante teil ist wenn es zu Fehlern kommt.

danke nochmals
noch ganz am Anfang vom Lernen ...
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

foto2004 hat geschrieben: Samstag 5. Juni 2021, 11:47 Dieses "requests.exceptions.ConnectionError:" Stand ja in der ganzen Fehlermeldung (xZeilen) ganz unten und ich denke dass das der relevante teil ist wenn es zu Fehlern kommt.
Mehr oder weniger. "requests.exceptions.ConnectionError" deckt nur einen Teil der Fehler ab, die im Kontext von HTTP wirklich auftreten können. M. M. n. ist das für eine Verfügbarkeitsüberprüfung nicht ausreichend, aber wenn es das ist, was du möchtest, dann nimm diese Exception. "requests.exceptions.RequestException" ist die Basis-Exception, von der alle anderen Exceptions des Moduls erben. Fängt man das ab, fängt man auch "requests.exceptions.ConnectionError" sowie alle weiteren Fehler, die auftreten können ab. Die entsprechende Passage in meinem Beispiel führt dazu, dass alle Fehler, einschließlich einschlägiger HTTP Status-Codes, über einen Kamm geschoren worden. Das will man in den meisten Fällen eher vermeiden – Für eine einfache Verfügbarkeitsabfrage und in Kombination mit der Fehlerausgabe ist das aber vielleicht ganz passend. S. a.: https://docs.python-requests.org/en/mas ... exceptions
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@foto2004,

also falls du Zugriff auf den Server hast, und so verstehe ich deinen letzten Post, dann würde ich nicht von Außen prüfen ob der Server abgestürzt ist.
Das Monitoring wurde ja auch schön vorgeschlagen.

Zudem gibt es Tools, die dir die Überwachung des Server abnehmen und diesen auch im Notfall neu starten.
foto2004
User
Beiträge: 16
Registriert: Samstag 27. Juni 2020, 12:57

Ja es gibt tools Duke das können aber das mit dem Neustart funktioniert da nicht so wie es soll und so muss immer per Hand nachgeholfen werden. (ist halt so ne gewachsene Struktur) .
Ist ein Server in einer Virtuellen Umgebung. Ich bin mir halt einfach ein Script am schreiben dass mir per Telegram eine Nachricht schickt damit ich das Dingens wieder Hochkitzeln kann und er nicht zu lange offline ist. Abe danke für eure Hilfe es hat mir sehr weiter geholfen.
noch ganz am Anfang vom Lernen ...
Antworten