Une alternative au bloc
try except
if this article is not in your language, use the Google Translate widget
⬈ (bottom of page for Mobile version ⬇)
Un gestionnaire de contexte en Python est généralement utilisé comme expression dans une instruction, le mot clé
with
permet de gérer une ressource en garantissant l'invocation d'une méthode
d'acquisition et d'une autre de libération de cette ressource. Un gestionnaire de contexte contient une méthode appelée au début et une méthode appelée à la fin.
La méthode
__enter__
est appelée avant le début de l'instruction
with
. La méthode
__exit__
est appelée après la dernière instruction de la méthode
with
. De plus, les gestionnaires de contexte sont très utiles en cas d'exception de notre programme
-
Voici un premier exemple, avec :
- une gestion d'erreur
- une écriture d'un log
- un affichage du message d'erreur via une boite de dialogue
Ici la boite de dialogue peut être très utile pour informer l'utilisateur
si le script est lancé depuis Dynamo Player.
import sys
import clr
import System
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import MessageBox, MessageBoxButtons, MessageBoxIcon
my_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments)
pf_path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFilesX86)
sys.path.append(pf_path + '\\IronPython 2.7\\Lib')
import logging
## Start create logger Object ##
logger = logging.getLogger("MyLogger")
# set to DEBUG
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(funcName)s :: %(message)s')
# create handler
file_handler = logging.FileHandler(my_path + '\\MyLogger.log', mode='a')
file_handler.setLevel(logging.ERROR)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.disabled = False
class ValidationError(Exception):
def __init__(self, typeError = "Error", messageError = "An error occurred"):
self._typeError = typeError
self._messageError = messageError
Exception.__init__(self, self._typeError)
self.CMessageBox()
def __str__(self):
return "{} : {}".format(self._typeError , self._messageError)
def CMessageBox(self):
MessageBox.Show(self._messageError, self._typeError, MessageBoxButtons.OK, MessageBoxIcon.Error)
class ErrorContextManager:
def __init__(self):
pass
def __enter__(self):
print("Context Successfully Started\n")
return self
def __exit__(self, exc_type, exc_value, exc_tb):
if exc_type:
exc_tbnext = exc_tb
lst_lines_error = []
for i in range(10):
if exc_tbnext is not None:
lst_lines_error.append(str(exc_tbnext.tb_lineno))
exc_tbnext = exc_tbnext.tb_next
else:
break
print(lst_lines_error)
error = "Error : {} at lines : line : {}".format( exc_value, " -> line : ".join(lst_lines_error))
logger.exception("{}\n{}".format(exc_type.__name__, error))
raise ValidationError(exc_type.__name__, error)
else:
print("Successfully Exited From Context\n")
return self
with ErrorContextManager() as sc:
test1 = 10 / 2
test2 = 10 / 2
test3 = 4 / 1
test1 = 10 / 2
test2 = 10 / 3
test3 = 4 / 1
test1 = 10 / 2
test2 = 10 / 1
test3 = 4 / 1
test1 = 10 / 2
test2 = 10 / 1
test3 = 4 / 0
test1 = 10 / 2
test2 = 10 / 1
test3 = 4 / 1
test2 = 10 / 2
test3 = 4 / 2
test1 = 10 / 2
test2 = 10 / 3
test3 = 4 / 9
test1 = 10 / 2
test2 = 10 / "2"
test3 = 4 / 2
.
-
Un autre exemple avec Civil 3D CPython3/PythonNet (2.5.x)
Avec le mot clé
with
, lors d'un appel d'une méthode .Net, IronPython appelle la méthode Dispose()
(ouClose()
) automatiquement lors de la sortie du bloc with
.
À ce jour, ce n'est pas le cas pour Python.NET (2.5.x) avec le moteur CPython3, ce qui peut poser quelques soucis de débogage lors d'erreurs.
En attentant une meilleure prise en charge du mot clé
with
sur les objets .Net IDisposable
, voici une amélioration de la gestion d'erreurs avec un context
manager.Code Python
import sys
import clr
# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')
# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *
# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *
class ErrorContextManager:
def __init__(self):
self.typeError = None
self.tracebackError = None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_tb):
if exc_type:
error = "{} at line {}\n".format( exc_value, exc_tb.tb_lineno)
self.typeError = exc_type.__name__
self.tracebackError = error
return self
def CheckError(self):
assert self.typeError is None, "{} : {}".format(self.typeError, self.tracebackError)
adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor
tv = []
with adoc.LockDocument():
with adoc.Database as db:
with db.TransactionManager.StartTransaction() as t:
with ErrorContextManager() as sc:
bt = t.GetObject(db.BlockTableId, OpenMode.ForWrite)
btr = t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
for oid in btr:
bl = t.GetObject(oid, OpenMode.ForRead)
if isinstance(bl, DBText):
tv.append(bl.TextString)
t.Commit()
sc.CheckError()
OUT = tv
0 commentaires:
Enregistrer un commentaire