2010-11-23 18 views
1

Je connais l'instruction with pour la gestion des ressources Python. Quelles autres préoccupations existe-t-il pour le code de sécurité d'exception en Python?Quel est l'état de la sécurité des exceptions en Python?

EDIT: Le souci ici est avec l'ouverture des fichiers et autres. Par exemple, supposons qu'une fonction init déclenche une exception. Quel est l'état de l'objet initialisé?

+1

Euh, de quoi parlez-vous? La sécurité de quoi? Cela semble être un sujet assez vaste. Quelle est votre question? – Falmarri

+1

L'objet existe déjà avant que '__init __()' soit appelé - c'est ce que le premier argument, habituellement appelé 'self', est - mais il n'est pas encore initialisé. Si une exception se produit au cours de ce processus, il se peut qu'il ne soit que partiellement ou même complètement non initialisé, selon la façon dont l'exception est traitée et par quoi. – martineau

+0

Voici ce que je voulais dire à propos d'un objet qui n'est pas initialisé correctement en fonction de la façon dont une exception se produisant dans la méthode '__init __()' a été gérée:! [Exemple de code] (http://dl.dropbox.com/u/5508445/stackoverflow /__init__exception.png). – martineau

Répondre

5

For instance, suppose an init function raises an exception. What is the state of the object being initialized?

Indice. En cas de doute, exécutez une expérience.

>>> class Partial(object): 
...  def __init__(self): 
...   self.a= 1 
...   raise Exception 
...   self.b= 2 
... 
>>> p= Partial() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in __init__ 
Exception 
>>> p 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'p' is not defined 

L'instruction - dans son ensemble - échoue. Objet non créé. Variable non affectée D'autres questions?

En C++, les choses sont tellement plus complexes. En Python, l'objet est simplement rejeté.

+4

Si tout le monde a fait une expérience en cas de doute, nous aurions 90% moins de questions Python sur SO - c'est un très bon conseil :-) –

+2

@ THC4k souvent juste essayer quelque chose que quelqu'un pose et afficher les résultats fait un réponse solide. Sshhh ... ne le dis pas à tout le monde ... – JAL

+1

@ THC4k D'autre part, il est bon de demander que vous obtenez des connaissances plus profondes que par l'expérience. –

0

Python ne ressemble pas à C++. Les exceptions produisent des backtraces utiles. Si vous prenez des entrées d'utilisateur, prenez les exceptions appropriées (comme EOFError) mais sinon, vous n'avez rien de spécial à faire pour éviter les exceptions. Si un programme fait quelque chose d'inattendu et déclenche une exception, utilisez le vidage de pile résultant pour déboguer votre problème. Si vous recherchez une disponibilité extrêmement élevée, vous pouvez envelopper votre niveau supérieur avec une try/except dans une boucle avec un journal et redémarrer.

+0

Forte Exception La sécurité n'a rien à voir avec les backtraces, etc. Cela doit être fait si le système est dans un état cohérent si une exception est levée. A moins que Python ne fasse tout dans un bloc java-like 'try' et applique ensuite tous les changements ... ce qui signifie qu'aucune des modifications de l'état n'est appliquée sauf s'il n'y a pas d'exceptions, alors python lui-même n'est pas intrinsèquement S.E.S. Oui, S.E.S. en C++ est difficile à faire aussi. mais il ne s'agit pas seulement de pouvoir «attraper» des exceptions. – mawalker

3

Si vous poser des questions sur la langue construit:

  • Utilisez try: except: else: il assure que vous ne prendre de mauvaises exceptions.
  • Réfléchissez bien avant attrapez BaseException, Exception ou utiliser nu except: que vous pouvez attraper easly à beaucoup:
    • vos fautes d'orthographe - NameError, ImportError
    • tentative de l'utilisateur de mettre fin à votre programme. KeyboardInterrupt, SystemExit
    • erreurs qui indique la mise en œuvre incomplète: NotImplementedError
  • Si vous décidez d'intercepter des exceptions génériques les journaux à l'aide log.exception('your message', e)
  • Gardez à l'esprit que les exceptions en Python sont également utilisés pour le contrôle des flux réguliers (comme StopIteration exception)
  • Utilisez la nouvelle syntaxe: except MyException as myex: au lieu de except MyException, myex:. Il est plus facile à lire pour les développeurs Python non expérimentés.

Voici un exemple qui attire NameError:

try: 
    this_doesn_not_exisit(); 
except Exception: #Don't do that! 
    pass 

print "But this line is still printed" 

Réponse à la question éditée:

  • En ce qui concerne les fichiers si vous lisez des fichiers de texte, utilisez toujours codecs.open au lieu d'ouvrir pour vous assurer que vous pouvez stocker en toute sécurité des chaînes Unicode.
  • En ce qui concerne le __init__ et l'état de l'objet. __init__ est un initialiseur de sorte que l'objet existe déjà lorsque __init__ est appelée. Si vous déclenchez une exception, le flux sera interrompu et l'objet ne sera stocké dans aucune variable, il sera donc collecté. Au moins c'est ma compréhension. Pensez que MyObject() est juste une fonction qui renvoie une valeur si vous relancez une exception vous ne renvoyez rien, le flux est interrompu et la valeur que vous avez assignée n'est pas modifiée.

Check this out:

>>> def throw(): raise Exception() 
... 
>>> a=1 
>>> a=throw() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in throw 
Exception 
>>> a 
1 

Voici un exemple pour prouver que l'objet est créé, même si vous élevez exception __init__. Je n'ai pas pu publier ce fragment dans les commentaires à @ S. Lott réponse:

>>> global_collection=[] 
>>> class Partial(object): 
... def __init__(self): 
...  self.test="test" 
...  global_collection.append(self) 
...  raise Exception() 
... 
>>> x=Partial() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in __init__ 
Exception 
>>> global_collection 
[<__main__.Partial object at 0xb74f8f6c>] 
>>> global_collection[0].test 
'test' 

MISE À JOUR: commentaires formulés faites par: McGuire @ Paul, @martineau, @aaronasterling

+0

J'inclurais enfin avec votre essai: except: else :. La clause finally fonctionne très bien pour s'assurer que les fichiers sont fermés, les ressources sont libérées, quelles que soient les erreurs qui sont apparues (qui sont temporaires). http://docs.python.org/reference/compound_stmts.html#try –

+0

FWIW, vous ne pouvez pas détecter une erreur de syntaxe. Cette erreur se produit avant que votre programme soit compilé et en cours d'exécution afin que votre instruction 'try' ne s'exécute pas à ce moment-là. – aaronasterling

+0

Il n'y a pas d'erreur de syntaxe dans votre premier exemple - 'this_doesn_not_exisit();' est syntaxiquement correct. Il existe cependant une exception 'NameError', car il n'y a rien de nommé' this_doesn_not_exisit'. Comme l'a expliqué Aaron, aucun 'except ', même générique, ne peut attraper un' SyntaxError' (mais je pense que votre conseil de ne pas utiliser ce genre est généralement valide). – martineau