Marking GC details as CPython-only

Hi I've tried (and failed) to find what GC details (especially finalizer semantics) are CPython only and which ones are not. The best I could find was the documentation of __del__ here: http://docs.python.org/2/reference/datamodel.html Things were pypy differs: * finalizers in pypy will be called only once, even if the object is resurrected. I'm not sure if this is detail or we're just plain incompatible. * pypy breaks cycles and runs finalizers in random order (but topologically correct), hence gc.garbage is always empty. I *think* this part is really just an implementation detail * we're discussing right now about running multiple finalizers. We want to run them in order, but if there is a link a -> b and a becomes unreachable, we want to reserve the right to call finalizer a then finalizer b, even if a.__del__ resurrects a. What do you think? Overall, the __del__ is baaad. Cheers, fijal

On 2013-02-13, at 19:48 , Maciej Fijalkowski wrote:
Hi
I've tried (and failed) to find what GC details (especially finalizer semantics) are CPython only and which ones are not. The best I could find was the documentation of __del__ here: http://docs.python.org/2/reference/datamodel.html
Things were pypy differs:
* finalizers in pypy will be called only once, even if the object is resurrected. I'm not sure if this is detail or we're just plain incompatible.
* pypy breaks cycles and runs finalizers in random order (but topologically correct), hence gc.garbage is always empty. I *think* this part is really just an implementation detail
* we're discussing right now about running multiple finalizers. We want to run them in order, but if there is a link a -> b and a becomes unreachable, we want to reserve the right to call finalizer a then finalizer b, even if a.__del__ resurrects a. What do you think?
Overall, the __del__ is baaad.
Cheers, fijal
There may be one more, although I'm not sure whether it's a GC artifact or something completely unspecified: if a context manager is part of a suspended stack (because it's in a generator) when the program terminates, cpython will run __exit__ but pypy will not -- # -*- encoding: utf-8 -*- class C(object): def __enter__(self): print ("entering") def __exit__(self, *args): print ("exiting") def gen(): with C(): yield r = gen() next(r) -- $ python2 test.py entering exiting $ python3 test.py entering exiting $ pypy test.py entering $ --

On Wed, Feb 13, 2013 at 9:09 PM, Xavier Morel <python-dev@masklinn.net> wrote:
On 2013-02-13, at 19:48 , Maciej Fijalkowski wrote:
Hi
I've tried (and failed) to find what GC details (especially finalizer semantics) are CPython only and which ones are not. The best I could find was the documentation of __del__ here: http://docs.python.org/2/reference/datamodel.html
Things were pypy differs:
* finalizers in pypy will be called only once, even if the object is resurrected. I'm not sure if this is detail or we're just plain incompatible.
* pypy breaks cycles and runs finalizers in random order (but topologically correct), hence gc.garbage is always empty. I *think* this part is really just an implementation detail
* we're discussing right now about running multiple finalizers. We want to run them in order, but if there is a link a -> b and a becomes unreachable, we want to reserve the right to call finalizer a then finalizer b, even if a.__del__ resurrects a. What do you think?
Overall, the __del__ is baaad.
Cheers, fijal
There may be one more, although I'm not sure whether it's a GC artifact or something completely unspecified: if a context manager is part of a suspended stack (because it's in a generator) when the program terminates, cpython will run __exit__ but pypy will not
-- # -*- encoding: utf-8 -*- class C(object): def __enter__(self): print ("entering") def __exit__(self, *args): print ("exiting")
def gen(): with C(): yield
r = gen() next(r) -- $ python2 test.py entering exiting $ python3 test.py entering exiting $ pypy test.py entering $ --
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/fijall%40gmail.com
I think it's well documented you should not rely on stuff like that being run at the exit of the interpreter. I think we'll try harder to run finalizers at the end of the interpreter (right now we only flush files). File the issue.

Hi, On Wed, Feb 13, 2013 at 8:22 PM, Maciej Fijalkowski <fijall@gmail.com> wrote:
I think it's well documented you should not rely on stuff like that being run at the exit of the interpreter.
Actually right now, at the exit of the interpreter, we just leave the program without caring about running any __del__. This might mean that in a short-running script no __del__ is ever run. I'd add this question to your original list: is it good enough, or should we try harder to run destructors at the exit? A bientôt, Armin.

On Wed, 13 Feb 2013 20:30:18 +0100 Armin Rigo <arigo@tunes.org> wrote:
Hi,
On Wed, Feb 13, 2013 at 8:22 PM, Maciej Fijalkowski <fijall@gmail.com> wrote:
I think it's well documented you should not rely on stuff like that being run at the exit of the interpreter.
Actually right now, at the exit of the interpreter, we just leave the program without caring about running any __del__. This might mean that in a short-running script no __del__ is ever run. I'd add this question to your original list: is it good enough, or should we try harder to run destructors at the exit?
Destructors should be run at exit like they would be in any other finalization situation. Anything else is dangerous, since important resources may not be finalized, committed, or released. (and by destructors I also mean weakref callbacks) Regards Antoine.

On Wed, Feb 13, 2013 at 9:40 PM, Antoine Pitrou <solipsis@pitrou.net> wrote:
On Wed, 13 Feb 2013 20:30:18 +0100 Armin Rigo <arigo@tunes.org> wrote:
Hi,
On Wed, Feb 13, 2013 at 8:22 PM, Maciej Fijalkowski <fijall@gmail.com> wrote:
I think it's well documented you should not rely on stuff like that being run at the exit of the interpreter.
Actually right now, at the exit of the interpreter, we just leave the program without caring about running any __del__. This might mean that in a short-running script no __del__ is ever run. I'd add this question to your original list: is it good enough, or should we try harder to run destructors at the exit?
Destructors should be run at exit like they would be in any other finalization situation. Anything else is dangerous, since important resources may not be finalized, committed, or released.
(and by destructors I also mean weakref callbacks)
Regards
Antoine.
I think Antoine is right (despite the fact that CPython docs clearly state that __del__s might not be run on the interpreter exit actually) Cheers, fijal

On Feb 13, 2013, at 08:30 PM, Armin Rigo wrote:
Actually right now, at the exit of the interpreter, we just leave the program without caring about running any __del__. This might mean that in a short-running script no __del__ is ever run. I'd add this question to your original list: is it good enough, or should we try harder to run destructors at the exit?
I've seen *tons* of small Python scripts that don't care about what happens, if anything, at program exit. Some have comments making that quite explicit. Sometimes, they even do so as performance improvements! When you care about start up costs, you often also care about tear down costs. Such scripts just expect that all their resources will get freed when the process exits. Of course, they're not always right (e.g. clean up tmp files), but it's pretty common, and I'm sure not just in Python. OTOH, relying on __del__ to clean up your tmp files seems rather dubious (well, frankly, so does most uses of __del__). Cheers, -Barry

On Wed, 13 Feb 2013 20:48:08 +0200 Maciej Fijalkowski <fijall@gmail.com> wrote:
Things were pypy differs:
* finalizers in pypy will be called only once, even if the object is resurrected. I'm not sure if this is detail or we're just plain incompatible.
I think this should be a detail.
* pypy breaks cycles and runs finalizers in random order (but topologically correct), hence gc.garbage is always empty. I *think* this part is really just an implementation detail
Agreed.
* we're discussing right now about running multiple finalizers. We want to run them in order, but if there is a link a -> b and a becomes unreachable, we want to reserve the right to call finalizer a then finalizer b, even if a.__del__ resurrects a. What do you think?
I think resurrecting objects from __del__ is crazy, so IMO what you suggest is fine. Regards Antoine.

Le Wed, 13 Feb 2013 20:50:51 +0000, Richard Oudkerk <shibturn@gmail.com> a écrit :
On 13/02/2013 7:25pm, Antoine Pitrou wrote:
I think resurrecting objects from __del__ is crazy, so IMO what you suggest is fine.
You mean like subprocess.Popen.__del__? I quite agree.
Ouch. I didn't know about that. Regards Antoine.
participants (6)
-
Antoine Pitrou
-
Armin Rigo
-
Barry Warsaw
-
Maciej Fijalkowski
-
Richard Oudkerk
-
Xavier Morel