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 :

try/except/finally et return


Sujet :

Python

  1. #1
    Membre actif Avatar de davguez
    Homme Profil pro
    Chercheur
    Inscrit en
    Octobre 2009
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2009
    Messages : 21
    Par défaut try/except/finally et return
    Bonjour,
    une question que je me pose: soi le programme suivant (executé sous python 2.7):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    def tst():
            try:
                    print 'bonjour'
                    print 5/0
                    return 'M'
            except:
                    print 'exception caught'
                    return 'E'
            finally:
                    print 'au revoir'
                    return 'F'
    print tst()
    j'obtiens comme résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    [david@localhost ~]$ python tst.py
    bonjour
    exception caught
    au revoir
    F
    donc, lors de l'appel à la fonction tst(), l'exception est attrapé et traité (bloc except) puis on passe au code de cleanup (block finally) mais visiblement le 'return' du bloc 'except' n'est pas pris en compte pouvez vous m'expliquer ce qui se passe dans le déroulement du programme ?

  2. #2
    Membre Expert

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Par défaut
    Je ne vois pas trop le problème*? Puisque (sauf exception non-capturée), le bloc finally: est toujours exécuté, son return écrase celui du bloc try (ou except en cas d’exception capturée)…

    Ça doit d’ailleurs bien être la seule situation où on peut avoir deux return d’exécutés dans une même fonction, non*?

  3. #3
    Membre actif Avatar de davguez
    Homme Profil pro
    Chercheur
    Inscrit en
    Octobre 2009
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2009
    Messages : 21
    Par défaut Moi ça m'étone
    en fait, ce qui m'étonne, c'est que l'on puisse 'ecraser' un return. Pour moi, un return provoque le passage du 'registre d'instruction' à l'appelant et devrait donc court-circuiter le bloc finally. Autrement dit, return ne termine pas la fonction mais met a jours une sorte de variable interne qui est retournée à la toute fin. Mais bon, je reconnais que c'est un cas d'école un peu pathologique, cet exemple.

    bye.

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 036
    Par défaut
    Ce que tu souhaites me fait plutôt penser à ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import sys
     
    def tst():
            try:
                    print 'bonjour'
                    print 5/0
                    return 'M'
            except:
                    print 'exception caught'
                    return 'E'
            else:
                    print 'au revoir'
                    return 'F'
    print tst()
    else à la place de finally.

    finally est dans tous les cas exécuté en fin de fonction.

    Voir la doc je sais plus où, pas le temps de chercher.

  5. #5
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    Citation Envoyé par davguez Voir le message
    en fait, ce qui m'étonne, c'est que l'on puisse 'ecraser' un return.
    Et bien en fait c'est dans la doc. En cas d’exception les clauses 'except' sont parcourues et celle correspondante évaluée. 'finally' étant toujours évaluée en dernier si celle ci retourne un return, raise ou une exception c'est celle qui ressort.
    Voici un exemple avec if:
    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
    20
    21
    22
    23
    24
    >>> v = True
    >>> def Foo():
    ...     if v:
    ...         print('ok')
    ...     else:
    ...         print('Nok')
    ... 
    >>> import dis
    >>> dis.dis(Foo)
      2           0 LOAD_GLOBAL              0 (v)
                  3 JUMP_IF_FALSE            9 (to 15)
                  6 POP_TOP             
     
      3           7 LOAD_CONST               1 ('ok')
                 10 PRINT_ITEM          
                 11 PRINT_NEWLINE       
                 12 JUMP_FORWARD             6 (to 21)
            >>   15 POP_TOP             
     
      5          16 LOAD_CONST               2 ('Nok')
                 19 PRINT_ITEM          
                 20 PRINT_NEWLINE       
            >>   21 LOAD_CONST               0 (None)
                 24 RETURN_VALUE
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    >>> def Bar():
    ...     try:
    ...         raise ZeroDivisionError('Oups')
    ...     except ZeroDivisionError:
    ...         pass
    ...     finally:
    ...         pass
    ... 
    >>> dis.dis(Bar)
      2           0 SETUP_FINALLY           42 (to 45)
                  3 SETUP_EXCEPT            16 (to 22)
    
      3           6 LOAD_GLOBAL              0 (ZeroDivisionError)
                  9 LOAD_CONST               1 ('Oups')
                 12 CALL_FUNCTION            1
                 15 RAISE_VARARGS            1
                 18 POP_BLOCK           
                 19 JUMP_FORWARD            19 (to 41)
    
      4     >>   22 DUP_TOP             
                 23 LOAD_GLOBAL              0 (ZeroDivisionError)
                 26 COMPARE_OP              10 (exception match)
                 29 JUMP_IF_FALSE            7 (to 39)
                 32 POP_TOP             
                 33 POP_TOP             
                 34 POP_TOP             
                 35 POP_TOP             
    
      5          36 JUMP_FORWARD             2 (to 41)
            >>   39 POP_TOP             
                 40 END_FINALLY         
            >>   41 POP_BLOCK           
                 42 LOAD_CONST               0 (None)
    
      7     >>   45 END_FINALLY         
                 46 LOAD_CONST               0 (None)
                 49 RETURN_VALUE
    Le return n'est pas 'écrasé', il est 'oublié' If the finally clause raises another exception or executes a return or break statement, the saved exception is dicarded / When a return, break or continue statement is executed in the try suite of a try...finally statement, the finally clause is also executed ‘on the way out.’ .

    @+

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 683
    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 683
    Par défaut
    Salut,

    donc, lors de l'appel à la fonction tst(), l'exception est attrapé et traité (bloc except) puis on passe au code de cleanup (block finally) mais visiblement le 'return' du bloc 'except' n'est pas pris en compte pouvez vous m'expliquer ce qui se passe dans le déroulement du programme ?
    finally étant exécuté dans tous les cas, la mouture proposée de tst retournera toujours 'F'.
    Son code pourrait être écrit ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def tst():
         try:
              print ('bonjour')
         except:
              print ('exception')
         print ('bye')
         return 'F'
    A quoi peut bien servir le finally?
    Dans ce cas, à pas grand chose!
    Son intérêt est de pouvoir nettoyer le contexte quoi qu'il se passe.
    Par exemple (et ils sont mauvais car Python a d'autres tours pour gérer cela),
    avant d'exécuter le block try, on doit acquérir un verrou ou ouvrir un fichier.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def test():
          v = lock.acquire() ou f = open(path)
          try:
               ...
               return 'success'
          except:
               ...
               return 'failure'
    finally permettra de fermer le fichier ou de rendre le verrou dans tous les cas, quelques soient les blocs exécutés. C'est une construction qui permet de simplifier l'écriture du code: pas de "goto", ni de sauvegarde du code de retour dans une variable locale avant de...

    Il n'est pas interdit d'y mettre un "return" mais que faire des autres dans ce cas sinon les ignorer?

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

Discussions similaires

  1. Try Catch Finally et Return
    Par melleb dans le forum C#
    Réponses: 21
    Dernier message: 28/07/2011, 12h30
  2. Avis de développeur sur mon code - Exception try/catch/finally
    Par psykoprof dans le forum Débuter avec Java
    Réponses: 15
    Dernier message: 02/06/2010, 00h01
  3. problème avec try except et try finally !?
    Par jano_dave dans le forum Débuter
    Réponses: 2
    Dernier message: 15/09/2009, 14h55
  4. Réponses: 3
    Dernier message: 12/12/2006, 18h58
  5. bloc try/except et API windows
    Par jakouz dans le forum API, COM et SDKs
    Réponses: 5
    Dernier message: 24/02/2005, 12h21

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