IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Comment continuer avec un excep


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 167
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 167
    Par défaut Comment continuer avec un excep
    Bonjour à tous,

    J'ai une fonction qui me permet d'envoyer des données sur un serveur distant, via le WiFi.

    Il y a une partie qui va définir le timeout

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c.setopt(c.TIMEOUT_MS, 3000)
    Il m'est arrivé une fois qu'une erreur se produise à ce niveau et le programme c'est arreté, et il ne le faut pas.

    J'ai donc mis un try:

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     print('[INFO] Sending data with PycURL')
            c = pycurl.Curl()
            c.setopt(c.URL, 'http://demo.eco-sensors.ch/include/save_aqi_n.php')
            c.setopt(c.HTTPHEADER, ['Accept: application/json','Content-Type: application/json'])
            c.setopt(c.POST, 1)
     
            try:
                # If you want to set a total timeout, say, 3 seconds
                c.setopt(c.TIMEOUT_MS, 3000)
                print("!!! CHECK HERE !!!")
                ## depending on whether you want to print details on stdout, uncomment either
                # curl.setopt(c.VERBOSE, 1) # to print entire request flow
                ## or
                # curl.setopt(p.WRITEFUNCTION, lambda x: None) # to keep stdout clean
     
                #body_as_dict = {"dev_id": "12", "path": "def", "target": "ghi"}
                body_as_dict = data
                body_as_json_string = json.dumps(body_as_dict) # dict to json
                body_as_file_object = StringIO(body_as_json_string)
     
                # prepare and send. See also: pycurl.READFUNCTION to pass function instead
                c.setopt(c.READDATA, body_as_file_object) 
                c.setopt(c.POSTFIELDSIZE, len(body_as_json_string))
                c.perform()
     
                status_code = c.getinfo(pycurl.RESPONSE_CODE)
                if status_code != 200:
                    print("Server returned HTTP status code {}".format(status_code))
                    #print('Device error: {}'.format(e))
     
                 c.close()
                 return 1
            except:
                c.close()
                // Log something
                continue
                return -1
    Si tout se passe bien, il ferme la connexion, et si ca ne passe mal il ferme aussi la connexion, mais le script doit continuer.

    Je ne sais pas trop si c'est juste comme je l'ai fait et surtout si je peux avoir un return -1, après le continue.
    Et comment je peux afficher le message d'erreur qui m'indiquerait la source de l'erreur? Car l'erreur peut aussi venir d'ailleur que du timeout

    J'ai aussi vu

    mais est-ce que je peux mettre un code après, ou il quitte immédiatement le try

    Mercii

  2. #2
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Salut,

    continue s'utilise si tu es dans une boucle, pour continuer celle-ci.

    Comme tu as un return dans ton code après le close() je suppose que tu n'es pas dans une boucle donc tu peux faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    except Exception as why:
        print("c.setopt error: %s" % why)
        c.close()
        return -1
    là tu capteras toutes les erreurs, tu sauras quel type d'erreur et éventuellement si tu as des plans B pour certains types d'erreur tu pourras adapter ton code pour capter spécifiquement ces erreurs-là.

    Mais s’il n'y a de toutes façons aucun plan B pour aucun type d'erreur sauf retourner -1 alors le code est bon comme ça.
    Le plus important c'est que tu aies la cause de l'erreur qui s'affiche.

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Idéalement, on attrape que les exceptions qu'on est capable de gérer et on met dans le block "try" que les instructions dont on veut "attraper et gérer" les exceptions.

    Dans votre cas, l'instruction qui génèrera l'exception sera c.perform().

    Il est préférable d'écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
            ...
            try:
                c.perform()
     
            except pycurl.error as e:
                print(e)
                if e.args[0] != pycurl.E_OPERATION_TIMEDOUT:
                    raise
                return -1
     
            else:
                status_code = c.getinfo(pycurl.RESPONSE_CODE)
                if status_code != 200:
                    print("Server returned HTTP status code {}".format(status_code))
                    #print('Device error: {}'.format(e))
     
                 return 1
            finally:
                c.close()
    Ce qui utilise toutes les fonctionnalités du try...except...else...finally.
    On attrape le timeout et on laisse l'appelant se débrouiller avec le reste.
    note: code non testé.

    Cela dit, la gestion normale d'un timeout, sera de réessayer l'opération un certain nombre de fois avant de laisser tomber et dire à l'appelant s'en débrouiller.

    Vous avez un chapitre intéressant sur la gestion des exceptions dans le Python tutorial.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 167
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 167
    Par défaut
    Bonjour et merci pour vos réponses

    Je viens d'essayer vos deux propositions.

    Premièrement, ceci marche très bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    except Exception as why:
        print("c.setopt error: %s" % why)
        c.close()
        return -1
    merci

    Pour tester ceci, en partant si mon code telq eu présenté, j'ai ajouté une erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c.setopt(cc.TIMEOUT_MS, 3000)
    Et il m'indique bien une erreue à ce niveau.



    J'ai aussi essayé de faire ce que propose wiztricks
    comme ceci (ATTENTION, j'ai laissé l'erreur volontaire c.setopt(cc.TIMEOUT_MS, 3000) qui devrait être c.setopt(c.TIMEOUT_MS, 3000)
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
     
    def send_curl(data):
             if C_URL:
                     save_log("INFO","Sending data with PycURL")
                     c = pycurl.Curl()
                     c.setopt(c.URL, 'http://demo.eco-sensors.ch/include/save_aqi_n.php')
                     c.setopt(c.HTTPHEADER, ['Accept: application/json','Content-Type: application/json'])
                     c.setopt(c.POST, 1)
     
                     # If you want to set a total timeout, say, 3 seconds
                     c.setopt(cc.TIMEOUT_MS, 3000)
                     ## depending on whether you want to print details on stdout, uncomment either
                     # curl.setopt(c.VERBOSE, 1) # to print entire request flow
                     ## or
                     # curl.setopt(p.WRITEFUNCTION, lambda x: None) # to keep stdout clean
     
             # preparing body the way pycurl.READDATA wants it
                     # NOTE: you may reuse curl object setup at this point
                     #  if sending POST repeatedly to the url. It will reuse
                     #  the connection.
                     #body_as_dict = {"dev_id": "12", "path": "def", "target": "ghi"}
                     body_as_dict = data
                     body_as_json_string = json.dumps(body_as_dict) # dict to json
                     body_as_file_object = StringIO(body_as_json_string)
     
            # prepare and send. See also: pycurl.READFUNCTION to pass function instead
                    c.setopt(c.READDATA, body_as_file_object) 
                    c.setopt(c.POSTFIELDSIZE, len(body_as_json_string))
     
                    try:
                            c.perform()
                    except Exception as e:
                            c.close()
                            save_log("ERROR","c.setopt error %s" % e)
                            return -1
     
                    # you may want to check HTTP response code, e.g.
                    status_code = c.getinfo(pycurl.RESPONSE_CODE)
                    if status_code != 200:
                            print("Server returned HTTP status code {}".format(status_code))
                            save_log("ERROR","Server returned HTTP status code {}".format(status_cocde))
                #print('Device error: {}'.format(e))
     
                     # don't forget to release connection when finished
                     c.close()
                     return 1
             else:
                     return 0
    Et là, ce ne semble pas fonctionner, mais il faudrait que j'apporte plus t'information, pour comprendre.

    Il faut savoir qu'il y a déjà un try au "niveau suppérieur", c'est à dire, au niveau où la fonction send_curl() est appelée

    # Sent to TTN or PycURL

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    try:
                  if LORA:
                           send_data(payload)
                           print('[INFO] Data sent to TTN')
                  if C_URL and LORA == False:
              r = send_curl(jsoncurl)
                          if r ==1:
                                   print('[INFO] Data sent with PycURL')
                          elif r == 0:
                                   print ('[INFO] CURL inactive')
                          elif r == -1:
                                   print('[ERROR] c.setoption ERROR. Check PycURL')
                          else:
                                   print('[WARMING] send_curl() returned %s. That s not normal' % r)
         else:
                          print('[WARNING] No data sent. LORA & C_URL inactive')
     
        except NameError:
                   print ("[ERROR] Failure in sending data")
    et c'est cette exception qui est générée
    except NameError:
    print ("[ERROR] Failure in sending data")
    Corrigez-moi, mais ca laisse à croire que l'erreur c.setopt(cc.TIMEOUT_MS, 3000) a interrompu la fonction send_curl() sans aller jusqu'au try qui sew trouve dans cette fonction, n'est-ce pas?

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par pierrot10 Voir le message
    ca laisse à croire que l'erreur c.setopt(cc.TIMEOUT_MS, 3000) a interrompu la fonction send_curl() sans aller jusqu'au try qui sew trouve dans cette fonction, n'est-ce pas?
    C'est ce que çà fait: seules les exceptions générées par les instructions entre try... et except sont attrapées, les autres remontent.

    Maintenant le NameError levé par c.setopt(cc.TIMEOUT_MS, 3000) est remontée par l'interpréteur Python pour vous signaler qu'il y a un problème dans le code.
    Si vous ne corrigez pas le code, elle va se répéter à volonté.

    Le c.perform qui lève un timeout lui n'arrive que de temps en temps et sauf si le délai d'attente est trop petit, il n'y a rien à corriger dans le code pour la faire partir...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 167
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 167
    Par défaut
    Donc ce que je pourrais faire, c'est de supprimer le try au niveau où la fonction send_curl() est appelée. Il ne sert à rien vu que ke try enblobe l'appelle de la fonction send_curl() et que dans cette derbiere il, y a un try.

    Puis je remets le try, avant c.setopt(c.TIMEOUT_MS, 3000), bref comme je l'ai fait initialement.

Discussions similaires

  1. [AC-2010] Comment remplir un formulaire continu avec une boucle en vba
    Par lololebricoleur dans le forum VBA Access
    Réponses: 22
    Dernier message: 09/12/2019, 20h30
  2. [HTML 4.0] Image à gauche avec texte moins haut que l'image. Comment continuer sous l'image.
    Par Quoidevieux dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 17/03/2013, 18h02
  3. Réponses: 6
    Dernier message: 17/08/2010, 21h34
  4. Comment linker avec odbc32.lib dans le code ? (avec gcc)
    Par _Audrey_ dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 06/11/2008, 17h40
  5. PRocédure stocké, comment appeler avec delphi?
    Par SkyDev dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/04/2004, 18h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo