RFC: Proposal: Deterministic Object Destruction
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Mar 3 22:29:22 EST 2018
On Sat, 03 Mar 2018 08:02:35 -0800, ooomzay wrote:
[...]
>> > But I am not! On the contrary RAII frees the programmer from even
>> > having to remember to close the file. The poster asked what would
>> > happen if the resource was deliberately kept open by storing a
>> > reference at global scope.
>>
>> You say that as if it were difficult to do, requiring the programmer to
>> take extraordinary steps of heroic proportion. It doesn't. It is
>> unbelievably easy to store the reference at global scope, which means
>> that the programmer needs to remember to close the file explicitly and
>> RAII doesn't help.
>
> Can you expand on what you mean by "unbelievably easy to store the
> reference at global scope". I will assume you are claiming that it is
> easy to _inadvertently_ store a global reference.
No.
Copy and paste this line:
--- %< ---------
x = 1
--- %< ---------
into a text file, and save it as "demo_global.py". Congratulations,
you've just created a reference in the global scope!
I told you it was easy.
Do you put your imports at the top of the module, as recommended? Every
one of those imported modules are references in the global scope.
Do you define classes and functions at the top level of your module?
Those too are references in the global scope.
I'll accept that, *typically*, imported modules, functions and classes
are unlikely to involve the sorts of resources that we care about closing
in a timely fashion. But other kinds of top-level instances may.
The point is, you want to *mandate* RAII as a *language feature* rather
than an implementation detail which Python interpreters are free to
choose or not choose on their own. This (probably?) will put a VERY high
burden on Jython, IronPython and Stackless, as well as anyone else who
tries making a Python interpreter. And for what benefit? Let's see:
- RAII doesn't make reference cycles go away, so we still need a
garbage collector that can break cycles;
- RAII rarely helps for objects in the module global namespace, and
many Python objects are in the global namespace;
- to make RAII work for heap objects, every implementation needs to
implement their own "smart pointers" or similar, otherwise the entire
idea is a bust; this adds significant complexity to interpreters that
aren't written in C++ (i.e. all of them apart from Nuitka);
- to make the RAII guarantees of timely resource closure work, you have
to impose significant mental burdens on the programmer:
* no cycles (avoid them, or use weak references);
* no globals;
* if you must use a global, then you are responsible for
manually deleting it in order to allow RAII to operate;
- to make the RAII guarantees work *well*, you need to introduce new
scoping rules (new to Python, not C++ ) where each indented block
(loops, if...else blocks etc) are new scopes; otherwise the lifetime
of a function scope could easily be too long.
> This problem with destruction of globals on exit is not unique to
> python. There are patterns to manage this for code you control, such as
> putting them all in one global "bucket" object and explicitly deleting
> it before exit.
The problem we have is, we want the resource to be closed in a timely
manner once we're done with it. And your solution is to put it in a "God
Object" that collects a whole lot of unrelated resources, then wait until
you are done with the last of the them, before closing any of them?
That's not a pattern managing the problem, that's a work-around that
fails to come even close to fixing the problem.
[...]
>> But as you said yourself, if the resource is held open in a global
>> reference, it will stay open indefinitely. And remember, global in this
>> context doesn't just mean the main module of your application, but
>> *every* module you import.
>
> Can you give an example of such a case where an application-managed
> (acquired/opened & released/closed) resource is referenced strongly by a
> 3rd party module at global scope? ...in my experience this pattern
> usually smells.
Regardless of whether it smells or not, it is allowed.
>> I think you have just put your finger on the difference between what
>> RAII *claims* to do and what it *actually* can do.
>
> I can assure you that RAII does what it says on the tin and is relied on
> in many critical systems to release resources robustly ... given the
> pre-requisite deterministic destruction.
Given the execution environment and design constraints of C++, I'm sure
RAII works fine in C++ (and any other language which may copy it).
But it is not a panacea that makes resource management go away. You
yourself have stated at least one limitation: if you hold a global
reference to the object then RAII won't help you.
So your proposal requires major changes to not just one but all (present
and future) Python interpreters, AND major changes to the way people
write Python code, in order to solve a problem which is already solved by
context managers and the with statement.
--
Steve
More information about the Python-list
mailing list