Dans Haskell, nous avons des exceptions asynchrones; nous pouvons utiliser throwTo
pour soulever une exception dans un autre thread:Est-ce que Python a un équivalent des fonctions 'mask' ou 'bracket' de Haskell?
throwTo :: Exception e => ThreadId -> e -> IO()
throwTo
déclenche une exception arbitraire dans le thread cible (GHC uniquement).
Pour pouvoir écrire du code avec des garanties comme « toujours libérer un verrou après l'avoir acquis », nous avons mask
d'exécuter du code dans lequel des exceptions asynchrones ne peuvent être reçues alors que le calcul bloque:
mask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Exécute un calcul d'E/S avec des exceptions asynchrones masqué. Autrement dit, tout thread qui tente de déclencher une exception dans le thread en cours avec
throwTo
sera bloqué jusqu'à ce que les exceptions asynchrones soient à nouveau masquées.
et une plus forte uninterruptibleMask
où des exceptions async ne seront pas soulevées du tout lors d'un calcul masqué:
uninterruptibleMask :: ((forall a. IO a -> IO a) -> IO b) -> IO b
Comme
mask
, mais le calcul masqué n'est pas interruptible
Le masquage est utilisé pour implémenter des abstractions de niveau supérieur telles que bracket
:
bracket :: IO a -- computation to run first ("acquire resource") -> (a -> IO b) -- computation to run last ("release resource") -> (a -> IO c) -- computation to run in-between -> IO c -- returns the value from the in-between computation
Lorsque vous souhaitez acquérir une ressource, faire un travail avec elle, puis relâchez la ressource, il est une bonne idée d'utiliser
bracket
, carbracket
installera le gestionnaire d'exceptions nécessaires pour libérer la ressource dans le cas où une exception est soulevée lors du calcul. Si une exception est déclenchée, alorsbracket
relance l'exception (après l'exécution de la version).
Si je comprends bien, Python a une (moins générale) sous forme d'exceptions asynchrones, avec la manifestation la plus notable étant KeyboardInterrupt
:
Raised lorsque l'utilisateur appuie sur la touche d'interruption (normalement contrôle - C ou Supprimer). Pendant l'exécution, une vérification des interruptions est faite régulièrement.
La documentation est imprécise quand le « contrôle des interruptions » peut se produire, mais il semble impliquer qu'un KeyboardInterrupt
peut être soulevée à tout moment dans l'exécution d'un programme. Il semble donc que les exceptions asynchrones de Python ont toutes les mêmes difficultés subtiles à maintenir la rectitude.
Par exemple, considérons un modèle comme celui-ci:
x = None
try:
x = acquire()
do_something(x) # (1)
finally:
if x is not None: # (2)
release(x)
Si une exception est soulevée au cours de (1)
, nous sommes assurés que le contenu du bloc finally
seront exécutés. Mais que se passe-t-il si un KeyboardInterrupt
est pendant (2)
?
Il semble fondamentalement impossible de garantir le nettoyage des ressources en présence d'exceptions asyc sans un moyen de les masquer. Y a-t-il une facilité pour cela, ou est-ce que nous comptons sur le ostrich algorithm?
Je pense que vous devez pratiquement installer votre propre gestionnaire de signal pour Ctrl-C si vous voulez faire cela. – user2357112