[Python-Dev] PEP 442 clarification for type hierarchies (original) (raw)
Antoine Pitrou solipsis at pitrou.net
Tue Aug 6 14:12:03 CEST 2013
- Previous message: [Python-Dev] PEP 442 clarification for type hierarchies
- Next message: [Python-Dev] PEP 442 clarification for type hierarchies
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Le Mon, 05 Aug 2013 22:30:29 +0200, Stefan Behnel <stefan_ml at behnel.de> a écrit :
Hmm, it's a bit unfortunate that tpfinalize() maps so directly to del(), but I think this can be fixed. In any case, each tpfinalize() function must only ever be called once, so if a subtype inherited the tpfinalize() slot from its parent, it mustn't be called again.
This is already dealt with by a custom bit in the GC header (cf. _PyGC_IS_FINALIZED, IIRC).
>> An obvious open question is how to deal with exceptions during >> finalisation. Any break in the execution chain would mean that a >> part of the type wouldn't be finalised. > > Let's come back to pure Python: > > class A: > def del(self): > 1/0 > > class B(A): > def del(self): > super().del() > self.cleanupresources()
What makes you think it's a good idea to call the parent type's finaliser before doing the local finalisation, and not the other way round? What if the subtype needs access to parts of the super type for its cleanup?
I'm not saying it's a good idea. I'm just saying that to reason about the C API, it is a good idea to reason about equivalent pure Python code. Since exceptions aren't implicitly silenced in pure Python code, they probably shouldn't in C code.
In other words, which makes more sense (at the C level):
try: super().tpfinalize() finally: localcleanup() or try: localcleanup() finally: super().tpfinalize() Should that order be part of the protocol or not? (well, not for del() I guess, but maybe for tpfinalize()?)
No, it is left to the user's preference. Since tp_finalize() is meant to be equivalent to del(), I think it's better if the protocols aren't subtly different (to the extent to which it is possible, of course).
Coming back to the del() vs. tpfinalize() story, if tpfinalize() first recursed into the super types, the top-most one of which then calls del() and returns, we'd get an execution order that runs Python-level del() methods before C-level tpfinalize() functions, but loose the subtype-before-supertype execution order for tpfinalize() functions.
Well... to get that, you'd have to subclass a pure Python class with a C extension type. Does that ever happen?
That might call for a three-step cleanup:
1) run all Python del() methods recursively 2) run all tpfinalize() functions recursively 3) run tpdealloc() recursively
I don't see any reason why tp_finalize should be distinct from del, while e.g. init and tp_init map to the exact same thing.
(you might wonder why tp_finalize isn't called tp_del, but that's because there is already something named tp_del - something which is obsoleted by PEP 442, incidently ;-)).
Regards
Antoine.
- Previous message: [Python-Dev] PEP 442 clarification for type hierarchies
- Next message: [Python-Dev] PEP 442 clarification for type hierarchies
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]