requests Fehlermeldung

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hm... hätte es nicht einen NameError geben müssen, wenn der Name falsch war?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Hyperion hat geschrieben:Hm... hätte es nicht einen NameError geben müssen, wenn der Name falsch war?
bei SSL und Protocol gab es den ja. aber bei ConnectionError hatte ich den nicht gesehen. Vllt hab ich den aber auch übersehen, weils nicht die letzte Fehlerausgabe war.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Ab und an tauchen noch Fehler auf wie "class ValueError" oder "class TypeError".

Meine try/except Konstruktionen sind noch ziemlich wild und alles andere als schön geschrieben. Da es aber natürlich auch in meinem Interesse ist, die Fehler so gut es geht zu behandel/nachzuvollziehen, poste ich jetzt mal, wie es bei mir aussieht:

Code: Alles auswählen

    def get_ticker_exchangepair(self,exchange,pairCode):
        zahl = 0
        i = 0
        while zahl<1:
            zahl+=1  # -> normalerweise Schleife nur einmal ausführen, außer es tritt fehler auf, dann zahl wieder auf 0 setzen
            try:
                if exchange =="TheRock":
                    #pairCode Form: BTCEUR
                    tickerInfo = rock.MarketData(pairCode)
                elif exchange == "Boerse2":
                    #paircode Form: XXBTZEUR
                    tickerInfo = k.query_public('Ticker',{'pair': pairCode})  
                else:
                    print("Ungültiger Exchange Name bei get_ticker_exchangepair übergeben!")
                    history("Ungültiger Exchange Name bei get_ticker_exchangepair übergeben!")
                    return None                    
            except requests.exceptions.ConnectionError:
                print("Keine Internetverbindung...bei {0} Tickerpair Abfrage:".format(exchange), sys.exc_info()[0])
                history("Keine Internetverbindung...bei {0} Tickerpair Abfrage:".format(exchange), sys.exc_info()[0])
                i+=1
                if i<=5:
                    print("...in 10 sekunden nochmal versuchen...")
                    history("...in 10 sekunden nochmal versuchen...")
                    zahl =0
                    sleep(10)
                    continue
                if i>5:
                    print("Fehler zu oft hintereinander aufgetreten, daher Abbruch des Bots")
                    history("Fehler zu oft hintereinander aufgetreten, daher Abbruch des Bots")
                    return None
            except requests.exceptions.SSLError as err:
                print("SSL Fehler bei {1}Abfrage : {0} Tickerpair ... ... tritt normalerweise nur selten auf, deswegen einfach in 5 sekunden nochmal probieren".format(err,exchange))
                history("SSL Fehler bei {1}Abfrage : {0} Tickerpair ... ... tritt normalerweise nur selten auf, deswegen einfach in 5 sekunden nochmal probieren".format(err,exchange))
                sleep(5)
                i+=1
                zahl=0
                continue
            except:
                print("Unbekannter Fehler bei {0} Tickerpair Abfrage :".format(exchange), sys.exc_info()[0])
                history("Unbekannter Fehler bei {0} Tickerpair Abfrage :".format(exchange), sys.exc_info()[0])
                i+=1
                if i<=5:
                    print("...in 5 sekunden nochmal versuchen...")
                    history("...in 5 sekunden nochmal versuchen...")
                    sleep(5)
                    zahl=0
                    continue
                if i>5:
                    print("Fehler zu oft hintereinander aufgetreten, daher Abbruch des Bots")
                    history("Fehler zu oft hintereinander aufgetreten, daher Abbruch des Bots")
                    return None
            return(tickerInfo)
Wie man hoffentlich sehen kann, ist der Sinn des Aufbaus, da die meisten Fehler nur kurzzeitig auftreten, dass bei einmaligen Auftreten eines Fehlers nicht gleich alles abgebrochen werden soll. Stattdessen soll halt kurz gewartet werden und es dann nochmal versucht werden. Erst bei 5 Fehlerversuchen wird dann aufgegeben.

Folgende Probleme treten dabei auf:
1)Auch KeyboardInterruptError wird so behandelt. Auf diese Weise (also Strg+C) beende ich meinen Bot zurzeit aber noch (was hoffentlich okay ist, oder?) Jedenfalls würde ich diesen einen Fehler gerne als Ausnahme definieren, das heißt also bei diesem speziellen Fehler soll er ruhig alles sofort abbrechen.

2) Ich bekomme keinen Traceback, sondern nur den Fehlernamen. Was muss ich schreiben um zusätzlich auch den Traceback zu bekommen?

3) Auch im Tutorial http://www.python-kurs.eu/python3_ausna ... ndlung.php steht leider nicht, wie man den Fehlernamen bei einem reinen except Block vernünftig bekommt. Dort steht nur das beispiel mit "print("Unexpected error:", sys.exc_info()[0])". Dieses "sys.exc_info()[0]" funktioniert aber nicht in meiner "history" Funktion, logisch, da ich keinen zweiten Parameter für history definiert habe (history schreibt den Text in eine .txt Datei). Also entweder müsste ich nun wissen, was genau "print" mit seinem zweiten Parameter anstellt und das für history nachbauen. Oder wir finden einen ohnehin besseren Weg, z.b mit Traceback, welcher sich einfach in eine Variable speichern lässt und über .format() dann an den Text dranhängen lässt.

4) Wenn ich einen sofortigen Abbruch des Skripts provozieren möchte, weil z.b. 5 Fehler aufgetreten sind, reicht es dann wenn ich einfach raise KeyboardInterrupt aufrufe (sobald dieser bei den ausnahmen ist) ? Oder gibt es da eine professionellere Möglichkeit?

5) Alle meine anderen Funktionen wie get_open_orders, get_balance usw. sind abgesehen von dem Inhalt des try-Block ganz genauso aufgebaut. Wenn ich also eine so eine Abfolge ändern möchte (z.b weil ich einen Traceback nun hinzufügen will), muss ich in all diesen Funktionen die except-Blöcke ändern. Daher würde es sich natürlich anbieten, eine Art except-Funktion zu schreiben, damit ich nur einmal alle except-blöcke in dieser except-funktion ändern muss und nicht ca. 10 mal :D Ist das so einfach machbar? Ich wüsste gerade nicht wie das dann aussehen müsste...

Diese 5 Fragen sind am wichtigsten.
Wenn sonst noch Mängel am Code sind, was definitv der Fall ist, dürft ihr das natürlich auch anmerken ;) Aber diese 5 Fragen haben bitte Vorrang :)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: TypeError und ValueError sollten eigentlich bei einer vernünftigen API nicht auftreten. Das sind dann wahrscheinlich nur eines vorhergehenden nicht richtig abgefangenen Fehlers. Wenn man Meldungen an verschiedenen Stellen ausgeben will, oder überhaupt nur Meldungen ein bißchen standardisiert verarbeiten will, bietet sich das logging-Modul an, dann braucht man auch nicht alle Meldungen doppelt zu schreiben!
Weder zahl noch i sind sinnvolle Variablennamen und zahl ist nicht mal eine sinnvolle Variable, schau doch mal genau nach, für was Du die überhaupt brauchst!
While-Schleifen, die zählen, ersetzt man praktischerweise durch eine for-Schleife. if und else solltest Du Dir dirngend auch nochmal anschauen.
Die von Dir verlinkte Seite ist selten eine Quelle guter Programmierung. Nackte except sollte man von den von Dir selbst schon genannten Gründen auch nie machen. Wenn Du dann tatsächlich nach 5mal den Fehler weiter gibst, dann mach das, indem Du in erneut raiset und nicht indem Du einen None-Wert zurückgibst, damit weiß der Aufrufer nämlich nicht, ob da jetzt alles gute gelaufen ist oder nicht.
Zu 5.: Du weißt ja jetzt wie man Funktionen per Variable weitergibt, jetzt kannst Du Dein Wissen endlich mal auf ein neues Problem anwenden.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens66: TypeError und ValueError sollten eigentlich bei einer vernünftigen API nicht auftreten. Das sind dann wahrscheinlich nur eines vorhergehenden nicht richtig abgefangenen Fehlers.
Ja, eig können diese Fehler nicht von mir verursacht sein, weil sie schließlich nur grob alle 2 stunden einmal auftreten und das eben an Stellen die sonst keinen Fehler produzieren.

Was ich jetzt auch noch hatte: Die API Abfragen liefern ja Antworten zurück wo die Daten in Listen und dictonaries verschachtelt sind. Deswegen muss ich auf eine bestimme sache dann eben mit Liste[0][1] oderso zugreifen. Nun gab es einen Fehler der sagte, dass meine Listenelement-Suche out of range wäre, obwohl es sonst immer klappt. Die Folgerung wäre, dass dort die API eine falsche/fehlerhafte Liste zurückgegeben hat. Aber wie kann ich sowas vorher kontrollieren? Gibt es etwas womit ich die Struktur von etwas prüfen kann? Also wenn die Rückgabe der API so aussieht :

Code: Alles auswählen

{'error': [], 'result': {'XXBTZEUR': {'bids': [['229.00000', '2.353', 1421076333], ['228.63700', '0.002', 1421076120]],
'asks': [['229.01000', '0.500', 1421076333], ['229.04000', '39.979', 1421076303]]}}}
Diese Ausgabe war gespeichert als "FullOrderBook_boerse2". Die erste Abfrage für die asks hat keinen Fehler verursacht. Erst die zweite Abfrage nach den bids hat den out of ragen Fehler verursacht, was ich mir nicht erklären kann.

Code: Alles auswählen

            bestask_price_u_volume_boerse2 = FullOrderBook_boerse2["result"]["XXBTZEUR"]["asks"][0]  
            bestbid_price_u_volume_boerse2 = FullOrderBook_boerse2["result"]["XXBTZEUR"]["bids"][0]
Da möchte ich irgendwie prüfen, ob die Ausgabe die ich bekommen habe, auch tatsächlich aus der hier ersichtlichen Menge an Listen und dictionaries besteht und zwar genau in dieser Reihenfolge. Wie kann ich das prüfen, bevor ich dann weiter damit hantiere und dann evlt irgendwo einen Fehler verursache(ich kann doch nicht jeden Listenzugriff in einen try-Block packen?!, also kann ich schon, aber das wäre doch wohl übertrieben)?
Sirius3 hat geschrieben: Wenn man Meldungen an verschiedenen Stellen ausgeben will, oder überhaupt nur Meldungen ein bißchen standardisiert verarbeiten will, bietet sich das logging-Modul an, dann braucht man auch nicht alle Meldungen doppelt zu schreiben!
logging hatte ich mir angeschaut, bevor ich mir selbst history zusammengebastelt habe. Ich bin aber mit den vielen Funktionen von logging nicht zurechtgekommen und wollte zu dem Zeitpunkt sowieso personalisierte Berichte in .txt dateien schreiben wo ich dann die Fehlermeldungen eig auch mit aufnehmen wollte, weshalb ich logging dann verworfen habe.
ich hatte als Config das hier gewählt :

Code: Alles auswählen

logging.basicConfig(filename='testlog.log',level=logging.DEBUG,format='%(asctime)s %(message)s')
Da aber keine Fehlermeldungen eingetragen wurden und ich es als zuviel Aufwand empfand nun rauszufinden, wie da nun die fehlermeldungen aufgenommen werden, hab ich halt einfach nur history genommen (weil ich schneller rausgefunden habe, wie man einen text in eine .txt Datei schreiben lassen kann).
Werde mir logging aber dann nochmal genauer anschauen...
Sirius3 hat geschrieben: Weder zahl noch i sind sinnvolle Variablennamen und zahl ist nicht mal eine sinnvolle Variable, schau doch mal genau nach, für was Du die überhaupt brauchst!
While-Schleifen, die zählen, ersetzt man praktischerweise durch eine for-Schleife. if und else solltest Du Dir dirngend auch nochmal anschauen.
Angenommen ich bräuchte diese Variablen hier, was wäre dann ein sinnvoller Name? Mir ist keiner eingefallen, außer vllt "counter", aber da bin ich immer etwas vorsichtig, weil es sowas möglicherweise ja schon python intern gibt und ich keine Namen doppelt verwenden will.
was meinst du bzgl if und else? Meinst du bei der Kontrolle ob i größer oder kleiner 5 ist, dass ich da auch einfach ein else als zweites nehmen könnte? Ja stimmt natürlich.. hab ich in dem Moment nicht dran gedacht, hätte ja sein können, dass ich i noch andere werte geben will oderso :D Allerdings würde ich das jetzt nicht als "dringend" bezeichnen. Ist da noch etwas unglücklich gemacht bzgl. if und else?
Spontan fällt mir nicht ein, wie ich das mit einer for schleife mache... geht ganz bestimmt, dazu müsste ich nur etwas komplizierter denken(also nach ein paar minuten würde mir sehr sicher eine Lösung einfallen, aber warum kompliziert, wenn es auch einfach geht?). Warum ist denn so eine einfache Lösung nicht gut?
Sirius3 hat geschrieben:Die von Dir verlinkte Seite ist selten eine Quelle guter Programmierung. Nackte except sollte man von den von Dir selbst schon genannten Gründen auch nie machen. Wenn Du dann tatsächlich nach 5mal den Fehler weiter gibst, dann mach das, indem Du in erneut raiset und nicht indem Du einen None-Wert zurückgibst, damit weiß der Aufrufer nämlich nicht, ob da jetzt alles gute gelaufen ist oder nicht.
... auf das erneute raisen des Fehlers nach 5 Fehlversuchen bin ich nicht gekommen... ja das wäre tatsächlich eine sinnvolle Möglichkeit, auch um den Bot dann eben sofort abzubrechen....
Sirius3 hat geschrieben: Zu 5.: Du weißt ja jetzt wie man Funktionen per Variable weitergibt, jetzt kannst Du Dein Wissen endlich mal auf ein neues Problem anwenden.
Nur weil ich etwas weiß, heißt das nicht gleich, dass ich auch auf die Lösung komme, siehe oben mit dem raise :D
Also ich stell mir das grad so vor, dass ich eben einen try-Block mit den zu machenden Dinge habe. So, nun sollen die except Blöcke folgen, welche immer gleich aussehen... wenn ich da stattdessen nun meine "fehlerfunktion" aufrufe, die die ganzen except Blöcke enthält, dann funktioniert das ja sicherlich nicht, weil der try- block nur darauf folgende except Anweisungen erkennt und nicht meine fehlerfunktion...
.. du sagst für die Lösung muss ich ganze Funktionen weitergeben... hmmm...aber welche und wieso? ...
ne.. also aktuell komme ich nicht drauf. Könnte aber vllt auch an meiner oben beschriebenen Vorstellung liegen. Könnte mir vorstellen, dass die komplett in die falsche richtung geht.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Serpens66 hat geschrieben:(also nach ein paar minuten würde mir sehr sicher eine Lösung einfallen, aber warum kompliziert, wenn es auch einfach geht?)
Weil einfach einfach einfach ist.
Hier die Funktion auf das Wesentliche reduziert:

Code: Alles auswählen

    def get_ticker_exchangepair(self, exchange, pair_code):
        for error_count in range(5):
            try:
                if exchange =="TheRock":
                    #pairCode Form: BTCEUR
                    return rock.MarketData(pair_code)
                elif exchange == "Boerse2":
                    #paircode Form: XXBTZEUR
                    return k.query_public('Ticker',{'pair': pair_code})  
                else:
                    raise AssertionError("Ungültiger Exchange Name bei get_ticker_exchangepair übergeben!")
            except requests.exceptions.ConnectionError as err:
                logging.exception("Keine Internetverbindung...bei {0} Tickerpair Abfrage:".format(exchange))
                last_error = err
            except requests.exceptions.SSLError as err:
                logging.exception("SSL Fehler bei {1}Abfrage : {0} Tickerpair ... ... tritt normalerweise nur selten auf, deswegen einfach in 5 sekunden nochmal probieren".format(err,exchange))
                last_error = err
            except Exception as err:
                logging.exception("Unbekannter Fehler bei {0} Tickerpair Abfrage :".format(exchange))
                last_error = err
            sleep(10)
        logging.exception("Fehler zu oft hintereinander aufgetreten, daher Abbruch des Bots")
        raise last_error
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Ich danke dir sehr!! :)

ich hab logging also jetzt wieder eingeschaltet. Das merkwürdige ist, dass im testlog ständig steht, was bei therock gemacht wird(das steht da auch, wenn ich nirgends in meinem Skript logging verwende, abgesehn von dem config-teil:
2015-01-12 22:26:59,657 Starting new HTTPS connection (1): http://www.therock.com
2015-01-12 22:27:01,470 "POST /api/get_balance HTTP/1.1" 200 None
....
Merkwürdig ist es deswegen, weil auch in dem Skript für diese Börse, wo eben die die requests gemacht werden, nichts mit logging steht und dieses auch nicht importiert wird... Über Boerse2 steht im logfile nichts. Die Balance Funktion sieht z.b so aus:

Code: Alles auswählen

    def GetBalance(self, currency):
        try:
            url = 'https://www.therock.com/api/get_balance'
            values = {
            'username' : self.username,
            'password' : self.password,
            'api_key'  : self.key,
            'type_of_currency' : currency
            }    
            Balance = requests.post('https://www.therock.com/api/get_balance', data=values).json()
            return Balance
        except Exception as err:
            raise err
( ist das mit dem except Block hier jetzt besser als nur reines except und return None ? Auch in Kombination mit dem von dir geschriebenen try-except Konstrukt welches auch get_balance umgibt. )

Jedenfalls sehe ich da wirklich nichts, was irgendwie dafür sorgen würde, dass das oben genannte in die logfile schreiben würde.
Woher kann das sonst kommen?? Kommt das vllt direkt von der Börse TheRock? Oder wie?
Ich würde das jedenfalls gerne abschalten, weil dadurch die logfile in kürzester Zeit mit diesen wenig hilfreichen Infos gefüllt wird und ziemlich stark anwächst.
Antworten