web-dev-qa-db-fra.com

Python - assert vs if & return

J'écris un script qui fait quelque chose dans un fichier texte (ce qu'il fait n'est pas pertinent pour ma question cependant). Donc, avant de faire quelque chose au fichier, je veux vérifier si le fichier existe. Je peux le faire, pas de problème, mais le problème est plutôt celui de l'esthétique.

Voici mon code, implémentant la même chose de deux manières différentes.

def modify_file(filename):
    assert os.path.isfile(filename), 'file does NOT exist.'


Traceback (most recent call last):
  File "clean_files.py", line 15, in <module>
    print(clean_file('tes3t.txt'))
  File "clean_files.py", line 8, in clean_file
    assert os.path.isfile(filename), 'file does NOT exist.'
AssertionError: file does NOT exist.

ou:

def modify_file(filename):
    if not os.path.isfile(filename):
        return 'file does NOT exist.'


file does NOT exist.

La première méthode produit une sortie qui est principalement triviale, la seule chose qui m'importe, c'est que le fichier n'existe pas.

La deuxième méthode renvoie une chaîne, c'est simple.

Ma question est: quelle méthode est la meilleure pour faire savoir à l'utilisateur que le fichier n'existe pas? L'utilisation de la méthode assert semble en quelque sorte plus Pythonic.

13
Vader

Vous iriez plutôt avec une troisième option : utilisez raise et une exception spécifique. Cela peut être l'une des exceptions intégrées , ou vous pouvez créer une exception personnalisée pour le travail.

Dans ce cas, j'utiliserais IOError , mais un ValueError pourrait également convenir:

def modify_file(filename):
    if not os.path.isfile(filename):
        raise IOError('file does NOT exist.')

L'utilisation d'une exception spécifique vous permet de déclencher d'autres exceptions pour différentes circonstances exceptionnelles et permet à l'appelant de gérer l'exception avec grâce.

Bien sûr, de nombreuses opérations sur les fichiers (comme open()) elles-mêmes augmentent déjà OSError; tester explicitement si le fichier existe peut être redondant ici.

N'utilisez pas assert; si vous exécutez python avec l'indicateur -O, toutes les assertions sont supprimées du code.

34
Martijn Pieters

assert est destiné aux cas où le programmeur appelant la fonction a fait une erreur, par opposition au tilisateur. L'utilisation de assert dans ces circonstances vous permet de vous assurer qu'un programmeur utilise correctement votre fonction pendant les tests, puis de la supprimer en production.

Sa valeur est quelque peu limitée car vous devez vous assurer d'exercer ce chemin dans le code, et vous voulez souvent gérer le problème en plus avec une instruction if distincte en production. assert est très utile dans des situations comme: "Je veux contourner ce problème si un utilisateur le rencontre, mais si un développeur le rencontre, je veux qu'il plante brutalement afin qu'il corrige le code qui appelle cela fonctionne pas correctement. "

Dans votre cas particulier, un fichier manquant est presque certainement une erreur de l'utilisateur et doit être traité en levant une exception.

12
Karl Bielefeldt

De singAssertionsEffectively

La vérification de isinstance () ne doit pas être surutilisée: si elle se détache comme un canard, il n'est peut-être pas nécessaire de se renseigner trop profondément pour savoir si elle l'est vraiment. Parfois, il peut être utile de transmettre des valeurs qui n'étaient pas prévues par le programmeur d'origine.

Lieux à considérer pour mettre des assertions:

checking parameter types, classes, or values
checking data structure invariants
checking "can't happen" situations (duplicates in a list, contradictory state variables.)
after calling a function, to make sure that its return is reasonable 

Le point global est que si quelque chose ne va pas, nous voulons que cela soit complètement évident dès que possible.

Il est plus facile d'attraper des données incorrectes au moment où elles entrent que de déterminer comment elles y sont arrivées plus tard lorsqu'elles causent des problèmes.

Les assertions ne remplacent pas les tests unitaires ou les tests système, mais plutôt un complément. Parce que les assertions sont un moyen propre d'examiner l'état interne d'un objet ou d'une fonction, elles fournissent "gratuitement" une assistance en clair à un test de boîte noire qui examine le comportement externe.

Les assertions ne doivent pas être utilisées pour tester les cas d'échec qui peuvent se produire en raison d'une mauvaise entrée utilisateur ou de défaillances du système d'exploitation/de l'environnement, comme un fichier introuvable . Au lieu de cela, vous devez déclencher une exception ou imprimer un message d'erreur ou tout ce qui est approprié. Une raison importante pour laquelle les assertions ne doivent être utilisées que pour les auto-tests du programme est que les assertions peuvent être désactivées au moment de la compilation.

Si Python est démarré avec l'option -O, les assertions seront supprimées et non évaluées. Donc, si le code utilise fortement les assertions, mais est critique en termes de performances, il existe un système pour les transformer (mais ne le faites pas à moins que ce soit vraiment nécessaire. Il a été scientifiquement prouvé que certains bogues n'apparaissent que lorsqu'un client utilise la machine et nous voulons que les assertions y aident aussi. :-))

5
dspjm