Re: RFC: Proposal: Deterministic Object Destruction (Posting On Python-List Prohibited)

2018-03-07 Thread Ooomzay
On Thursday, 1 March 2018 22:44:59 UTC, Rob Gaddi  wrote:
> On 03/01/2018 02:24 PM, Lawrence D’Oliveiro wrote:
> > On Thursday, March 1, 2018 at 6:44:39 PM UTC+13, Paul Rubin wrote:
> >> DOM trees are a classic example (see the various DOM modules in the
> >> Python stdlib).  Non-leaf nodes have a list of child nodes, child nodes
> >> have pointers back upwards to their parent, and each child node has
> >> pointers to its left and right siblings if they exist.  It's all very
> >> circular.
> > 
> > This is why you have weak refs.
> > 
> But making sure that the failure to use weakrefs doesn't memory leak the 
> program into the pavement is why you have background garbage collection 
> with intelligent cyclical reference breaking.

That is the worst justification for gc I have seen yet, and also the most 
truthful. gc.set_debug(gc.DEBUG_LEAK) is your friend my friends.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Layers of abstraction, was Re: RFC: Proposal: Deterministic Object Destruction

2018-03-06 Thread Ooomzay
On Wednesday, 7 March 2018 06:43:10 UTC, Ooomzay  wrote:
> On Tuesday, 6 March 2018 14:12:38 UTC, Peter Otten  wrote:
> > Chris Angelico wrote:
> > 
> > > On Tue, Mar 6, 2018 at 10:04 AM, Steven D'Aprano
> > > <steve+comp.lang.pyt...@pearwood.info> wrote:
> > >> # Later.
> > >> if __name__ = '__main__':
> > >> # Enter the Kingdom of Nouns.
> > > 
> > > Don't you need a NounKingdomEnterer to do that for you?
> > 
> > No, for some extra flexibility there should be a NounKingdomEntererFactory 
> 
> For example open().
> 
> > -- which of course has to implement the AbstractNounKingdomEntererFactory 
> > interface. 
> 
> For example a PEP 343 "Context Manager".
> 
> In the swamplands of the pythonistas the one-eyed man is BDFL!
> 
> Amen.

Damn. That should have read:-

In the swamplands of the pythonistas the man with a badly leaking boat is BDFL.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Layers of abstraction, was Re: RFC: Proposal: Deterministic Object Destruction

2018-03-06 Thread Ooomzay
On Tuesday, 6 March 2018 14:12:38 UTC, Peter Otten  wrote:
> Chris Angelico wrote:
> 
> > On Tue, Mar 6, 2018 at 10:04 AM, Steven D'Aprano
> >  wrote:
> >> # Later.
> >> if __name__ = '__main__':
> >> # Enter the Kingdom of Nouns.
> > 
> > Don't you need a NounKingdomEnterer to do that for you?
> 
> No, for some extra flexibility there should be a NounKingdomEntererFactory 

For example open().

> -- which of course has to implement the AbstractNounKingdomEntererFactory 
> interface. 

For example a PEP 343 "Context Manager".

In the swamplands of the pythonistas the one-eyed man is BDFL!

Amen.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-06 Thread Ooomzay

On Monday, 5 March 2018 23:06:53 UTC, Steven D'Aprano  wrote:
> On Mon, 05 Mar 2018 09:22:33 -0800, Ooomzay wrote:
> [...]
> > If you would like to have a shot at coding this without RAII, but
> > preserving the OO design, you will find that it is considerably
> > simpler than the with/context manager approach.
> 
> Preserving the OO design, you say? Okay, since my application apparently 
> isn't allowed to know that it is processing two files, I'll simply 
> delegate that to the object:
> 
> class C(A, B):
> def run(self):
> with open(self.a) as a:
> with open(self.b) as b:
> process(a, b)
> 
> # Later.
> if __name__ = '__main__':
> # Enter the Kingdom of Nouns.
> c = C()
> c.run()
> 
> There you go. Encapsulation and OO design.

1. This does not execute. It is only when you actually flesh out 
these deliberately minimal classes A, B & C with PEP232 paraphernalia
that we all be able to see clearly how much cleaner or messier 
things are with PEP232. 

2. Your Class C breaks A & B's encapsulation by inheriting rather than 
composing them. Apart from increasing coupling and preventing 
substitution, C contained A & B in this example to illustrate that there is 
no RAII related burden whatever_on this intermediate class as 
it manages no external resources directly. It does not even 
need to implement __del__.

3. You have assumed a single threaded application. Please imagine 
that A and B are classes managing some remote valves and maintain 
their own threads as well as a serial port for comms. And C is there to 
coordinate them towards some greater purpose.

If you would like to try and add PEP232 support to
classes A,B & C to the point that you can create
and destroy c = C() in an exception-safe way we may 
all learn something.

> I'm not trying to dissuade you from using RAII in your own applications, 
> if it works for you, great.

Unfortunately, despite having conquered it, without a _guarantee_ of this 
behaviour from the language, or at least one mainstream implementation, 
I will not invest in python again. Nor recommend any one else with a serious 
real world resource management application to do so. This was the original 
motive for my PEP.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 19:14:05 UTC, Paul Rubin  wrote:
> Ooomzay writes:
> > If you want to use RAII objects then you will make sure you avoid
> > adding them to orphan cycles by design. If you don't know how to do
> > that then don't write applications that manage critical resources.
> 
> My claim is managing critical resources with refcounts is bug-prone in
> the case where the refcounts can become arbitrarily large at runtime.

What case is that? Don't go there! You may be jaded because python forgives 
bad design practices and peeps are inclined to leak resources all over 
the place for no good reason whatever and then complain when they have 
trouble cleaning up or exiting!

> You say you wrote a program that worked that way, but it sounds
> horrendous and I'd like to know how you tested it, maintained it, kept
> it maintainable by other programmers, etc.  
> It's painful to even think about.

I too used to suffer pain with python - until I saw that light and 
worked out how to use it for RAII. So here's the keys for much less pain:-

* Use CPython (or C++ ;)

* Use RAII for every resource-holding class: Implement __del__ to release any 
resources acquired in __init__.  (This is significantly less effort, and more 
reliable than adding __enter__ & __exit__ to every class).

* Wrap your try-except blocks in functions to prevent exceptions persisting 
outside the handler because in python they leak. This is typically a very 
natural factorization.

* Take care not to create Cyclic Exceptions in your Exception handling logic.
 This was the one that had me scratching my head for a couple of hours the 
first 
time I inadvertantly created a cycle.

* If you have no application-level requirement for persistent orphan cycles, 
and few, if any, applications do, then disable gc on entry and raise an 
exception on exit, or any other convenient moment if there is any garbage 
to be collected.

* Immediately plug/bug any leaks that you discover. Do not let them build 
up or you will drown and loose faith that there can be a better way.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 17:58:40 UTC, Chris Angelico  wrote:
> On Tue, Mar 6, 2018 at 4:53 AM, Ooomzay wrote:
> > On Monday, 5 March 2018 14:21:54 UTC, Chris Angelico  wrote:
> >> On Tue, Mar 6, 2018 at 12:58 AM, Ooomzay wrote:
> >> > Here is my fixed example, if someone else could try it in CPython and 
> >> > report back that would be interesting:-
> >> >
> >> > class RAIIFileAccess():
> >> > def __init__(self, fname):
> >> > print("%s Opened" % fname)
> >> > self.fname = fname
> >> >
> >> > def __del__(self):
> >> > print("%s Closed" % self.fname)
> >> >
> >> > class A():
> >> > def __init__(self):
> >> > self.res = RAIIFileAccess("a")
> >> >
> >> > class B():
> >> > def __init__(self):
> >> > self.res = RAIIFileAccess("b")
> >> >
> >> > class C():
> >> > def __init__(self):
> >> > self.a = A()
> >> > self.b = B()
> >> >
> >> > def main():
> >> > c = C()
> >> > c.dostuff()
> >> >
> >> > main()
> >>
> >> Here's how I'd do it with context managers.
> >>
> >> from contextlib import contextmanager
> >>
> >> @contextmanager
> >> def file_access(fname):
> >> try:
> >> print("%s Opened" % fname)
> >> yield
> >> finally:
> >> print("%s Closed" % fname)
> >>
> >> @contextmanager
> >> def c():
> >> try:
> >> print("Starting c")
> >> with file_access("a") as a, file_access("b") as b:
> >> yield
> >> finally:
> >> print("Cleaning up c")
> >>
> >> def main():
> >> with c():
> >> dostuff() # NameError
> >
> >
> > Thank you for having a go...
> >
> > However you have broken the encapsulation of class A and B. These
> > are trivial for the sake of example. I should have used
> > _underscores (i.e. self._res) to make the intent of
> > this example more obvious.
> >
> > Please try again but preserving the integrity/encapsulation
> > of class A & B & C, just as the RAII example does.
> 
> What is B? Is it something that's notionally a resource to be managed?

Yes. For example a supply of electrical power controlled via a serial protocol  
to a programmable power supply - the file is a private detail used for the 
communications. And lets imagine that this powersupply object needs to keep 
track of some state such as the voltage - and it has a long lifetime - not just 
created then destroyed in scope of one function i.e. it is a substantial object.

> If so, you can trivially add another level to the nesting.

Please illustrate. I really do want to be able to compare like for like.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 14:21:54 UTC, Chris Angelico  wrote:
> On Tue, Mar 6, 2018 at 12:58 AM, Ooomzay wrote:
> > Here is my fixed example, if someone else could try it in CPython and 
> > report back that would be interesting:-
> >
> > class RAIIFileAccess():
> > def __init__(self, fname):
> > print("%s Opened" % fname)
> > self.fname = fname
> >
> > def __del__(self):
> > print("%s Closed" % self.fname)
> >
> > class A():
> > def __init__(self):
> > self.res = RAIIFileAccess("a")
> >
> > class B():
> > def __init__(self):
> > self.res = RAIIFileAccess("b")
> >
> > class C():
> > def __init__(self):
> > self.a = A()
> > self.b = B()
> >
> > def main():
> > c = C()
> > c.dostuff()
> >
> > main()
> 
> Here's how I'd do it with context managers.
> 
> from contextlib import contextmanager
> 
> @contextmanager
> def file_access(fname):
> try:
> print("%s Opened" % fname)
> yield
> finally:
> print("%s Closed" % fname)
> 
> @contextmanager
> def c():
> try:
> print("Starting c")
> with file_access("a") as a, file_access("b") as b:
> yield
> finally:
> print("Cleaning up c")
> 
> def main():
> with c():
> dostuff() # NameError
 

Thank you for having a go...

However you have broken the encapsulation of class A and B. These 
are trivial for the sake of example. I should have used
_underscores (i.e. self._res) to make the intent of
this example more obvious.

Please try again but preserving the integrity/encapsulation
of class A & B & C, just as the RAII example does.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 16:47:02 UTC, Steven D'Aprano  wrote:
> On Sun, 04 Mar 2018 16:58:38 -0800, Ooomzay wrote:
> 
> > Here is an example of a composite resource using RAII:-
> > 
> > class RAIIFileAccess():
> > def __init__(self, fname):
> > print("%s Opened" % fname)
> > def __del__(self):
> > print("%s Closed" % fname)
> > 
> > class A():
> > def __init__(self):
> > self.res = RAIIFileAccess("a")
> > 
> > class B():
> > def __init__(self):
> > self.res = RAIIFileAccess("b")
> > 
> > class C():
> > def __init__(self):
> > self.a = A()
> > self.b = B()
> >  
> > def main():
> > c = C()
> 
> Looking at that code, my major thought is  that there is far too much OO 
> design, not enough simplicity.

If this is far too much OO for you then RAII will be of no 
interest to you.

This example was specifically in response to a request to
illustrate the relative simplicity of RAII in the case of a 
composite (OO) resource.

> Perhaps I'm missing something, but I have no idea what benefit there is 
> in that style of code over:
> 
> with open('a') as a:
> with open('b') as b:
> process(a, b)

Encapsulation. Your application code is now managing details 
that should be hidden in the object. This PEP and RAII are
unashamedly targeted at OO designs.

If you would like to have a shot at coding this without RAII,
but preserving the OO design, you will find that it is 
considerably _simpler_ than the with/context manager approach.

> So long as you only process a or b inside the nested block, you are 
> guaranteed that they will be open.
> 
> And unlike your RAII example, they will be closed when you exit, 
> regardless of how many references to them you have, regardless of whether 
> an exception occurs or not, regardless of whether there are cycles or 
> whether they are globals or whether the interpreter is shutting down.

If you choose RAII you will not be cavalier with your references.

> I think that at this point, you have convinced me that you want to impose 
> enormous costs on all Python interpreters *and* Python developers, in 
> order to allow you to write C++ code in Python rather than learn Pythonic 
> idioms like the with statement.

On interpreters yes. On developers no. You can carry on exactly as you are.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 15:17:13 UTC, bartc  wrote:
> On 05/03/2018 13:58, Ooomzay wrote:
> > On Monday, 5 March 2018 11:24:37 UTC, Chris Angelico  wrote:
> >> On Mon, Mar 5, 2018 at 10:09 PM, Ooomzay wrote:
> >>> Here is an example of a composite resource using RAII:-
> >>>
> >>> class RAIIFileAccess():
> >>>  def __init__(self, fname):
> >>>  print("%s Opened" % fname)
> >>>  def __del__(self):
> >>>  print("%s Closed" % fname)
> >>>
> >>> class A():
> >>>  def __init__(self):
> >>>  self.res = RAIIFileAccess("a")
> >>>
> >>> class B():
> >>>  def __init__(self):
> >>>  self.res = RAIIFileAccess("b")
> >>>
> >>> class C():
> >>>  def __init__(self):
> >>>  self.a = A()
> >>>  self.b = B()
> >>>
> >>> def main():
> >>>  c = C()
> >>>
> >>> Under this PEP this is all that is needed to guarantee that the files "a"
> >>> and "b" are closed on exit from main or after any exception has been 
> >>> handled.
> >>
> >> Okay. And all your PEP needs is for reference count semantics, right?
> >> Okay. I'm going to run this in CPython, with reference semantics. You
> >> guarantee that those files will be closed after an exception is
> >> handled? Right.
> >>
> >>>>> def main():
> >> ... c = C()
> >> ... c.do_stuff()
> >> ...
> >>>>> main()
> >> a Opened
> >> b Opened
> >> Traceback (most recent call last):
> >>File "", line 1, in 
> >>File "", line 3, in main
> >> AttributeError: 'C' object has no attribute 'do_stuff'
> >>>>>
> >>   
> >> Uhh I'm not seeing any messages about the files getting closed.
> > 
> > Then that is indeed a challenge. From CPython back in 2.6 days up to 
> > Python36-32 what I see is:-
> > 
> > a Opened
> > b Opened
> > Traceback (most recent call last):
> > ...
> > AttributeError: 'C' object has no attribute 'dostuff'
> > a Closed
> > b Closed
> > 
> >> Maybe exceptions aren't as easy to handle as you think?
> > 
> > Well there is a general issue with exceptions owing to the ease
> > with which one can create cycles that may catch out newbs. But
> > that is not the case here.
> > 
> >> Or maybe you
> >> just haven't tried any of this (which is obvious from the bug in your
> >> code
> > 
> > Or maybe I just made a typo when simplifying my test case and failed to 
> > retest?
> > 
> > Here is my fixed case, if someone else could try it in CPython and report 
> > back that would be interesting:-
> > 
> > class RAIIFileAccess():
> >  def __init__(self, fname):
> >  print("%s Opened" % fname)
> >  self.fname = fname
> > 
> >  def __del__(self):
> >  print("%s Closed" % self.fname)
> > 
> > class A():
> >  def __init__(self):
> >  self.res = RAIIFileAccess("a")
> > 
> > class B():
> >  def __init__(self):
> >  self.res = RAIIFileAccess("b")
> > 
> > class C():
> >  def __init__(self):
> >  self.a = A()
> >  self.b = B()
> > 
> > def main():
> >  c = C()
> >  c.dostuff()
> > 
> > main()
> 
> I get A and B closed messages when running on CPython 2.7 and 3.6, with 
> the code run from a .py file. (I never use interactive mode.)
> 
> But not when running on a PyPy version of 2.7 (however that is not CPython).

Thanks bartc, I have made the example more complete by adding an exception 
scope - this means it works as designed - in any context. See my reply to Chris.

We do not expect this to work in PyPy.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 14:36:30 UTC, Chris Angelico  wrote:
> On Tue, Mar 6, 2018 at 1:25 AM, Ooomzay wrote:
> > Ahah... I see now you are running it from a shell so the exception is 
> > staying in scope. We just need to include normal exception handling in the 
> > example to fix this:-
> >
> > def main():
> > try:
> > c = C()
> > c.dostuff()
> > except:
> > print("Boom!")
> >
> > main()
> >
> 
> So RAII depends on absorbing every exception close to where the
> resource is being managed? You can't permit that exception to bubble
> up lest the resource get leaked??

The exception can bubble up as many layers as you like but in python the 
exception leaks out of the handling context and needs its scope limiting. I 
have previously pointed out that such scoping is still recommended and that a 
function is pythons scoping construct - so use them for the job.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 13:59:35 UTC, Ooomzay  wrote:
> On Monday, 5 March 2018 11:24:37 UTC, Chris Angelico  wrote:
> > On Mon, Mar 5, 2018 at 10:09 PM, Ooomzay wrote:
> > > Here is an example of a composite resource using RAII:-
> > >
> > > class RAIIFileAccess():
> > > def __init__(self, fname):
> > > print("%s Opened" % fname)
> > > def __del__(self):
> > > print("%s Closed" % fname)
> > >
> > > class A():
> > > def __init__(self):
> > > self.res = RAIIFileAccess("a")
> > >
> > > class B():
> > > def __init__(self):
> > > self.res = RAIIFileAccess("b")
> > >
> > > class C():
> > > def __init__(self):
> > > self.a = A()
> > > self.b = B()
> > >
> > > def main():
> > > c = C()
> > >
> > > Under this PEP this is all that is needed to guarantee that the files "a"
> > > and "b" are closed on exit from main or after any exception has been 
> > > handled.
> > 
> > Okay. And all your PEP needs is for reference count semantics, right?
> > Okay. I'm going to run this in CPython, with reference semantics. You
> > guarantee that those files will be closed after an exception is
> > handled? Right.
> > 
> > >>> def main():
> > ... c = C()
> > ... c.do_stuff()
> > ...
> > >>> main()
> > a Opened
> > b Opened
> > Traceback (most recent call last):
> >   File "", line 1, in 
> >   File "", line 3, in main
> > AttributeError: 'C' object has no attribute 'do_stuff'
> > >>>
> >  
> > Uhh I'm not seeing any messages about the files getting closed.
> 
> Then that is indeed a challenge. From CPython back in 2.6 days up to 
> Python36-32 what I see is:-
> 
> a Opened
> b Opened
> Traceback (most recent call last):
> ...
> AttributeError: 'C' object has no attribute 'dostuff'
> a Closed
> b Closed
> 
> > Maybe exceptions aren't as easy to handle as you think? 
> 
> Well there is a general issue with exceptions owing to the ease
> with which one can create cycles that may catch out newbs. But
> that is not the case here.
> 
> > Or maybe you
> > just haven't tried any of this (which is obvious from the bug in your
> > code 
> 
> Or maybe I just made a typo when simplifying my test case and failed to 
> retest?
> 
> Here is my fixed case, if someone else could try it in CPython and report 
> back that would be interesting:-
> 
> class RAIIFileAccess():
> def __init__(self, fname):
> print("%s Opened" % fname)
> self.fname = fname
> 
> def __del__(self):
> print("%s Closed" % self.fname)
> 
> class A():
> def __init__(self):
> self.res = RAIIFileAccess("a")
> 
> class B():
> def __init__(self):
> self.res = RAIIFileAccess("b")
> 
> class C():
> def __init__(self):
> self.a = A()
> self.b = B()
> 
> def main():
> c = C()
> c.dostuff()
> 
> main()
> 
> > You keep insisting that this is an easy thing.  > We keep pointing out
> > that it isn't. Now you're proving that you haven't even attempted any
> > of this. 
> 
> Nonsense. But you have got a result I have never seen in many years 
> and I would like to get to the  bottom of it.

Ahah... I see now you are running it from a shell so the exception is staying 
in scope. We just need to include normal exception handling in the example to 
fix this:-


class RAIIFileAccess():
def __init__(self, fname):
print("%s Opened" % fname)
self.fname = fname
def __del__(self):
print("%s Closed" % self.fname)


class A():
def __init__(self):
self.res = RAIIFileAccess("A")


class B():
def __init__(self):
self.res = RAIIFileAccess("B")


class C():
def __init__(self):
self.a = A()
self.b = B()


def main():
try:
c = C()
c.dostuff()
except:
print("Boom!")

main()




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, 5 March 2018 11:24:37 UTC, Chris Angelico  wrote:
> On Mon, Mar 5, 2018 at 10:09 PM, Ooomzay wrote:
> > Here is an example of a composite resource using RAII:-
> >
> > class RAIIFileAccess():
> > def __init__(self, fname):
> > print("%s Opened" % fname)
> > def __del__(self):
> > print("%s Closed" % fname)
> >
> > class A():
> > def __init__(self):
> > self.res = RAIIFileAccess("a")
> >
> > class B():
> > def __init__(self):
> > self.res = RAIIFileAccess("b")
> >
> > class C():
> > def __init__(self):
> > self.a = A()
> > self.b = B()
> >
> > def main():
> > c = C()
> >
> > Under this PEP this is all that is needed to guarantee that the files "a"
> > and "b" are closed on exit from main or after any exception has been 
> > handled.
> 
> Okay. And all your PEP needs is for reference count semantics, right?
> Okay. I'm going to run this in CPython, with reference semantics. You
> guarantee that those files will be closed after an exception is
> handled? Right.
> 
> >>> def main():
> ... c = C()
> ... c.do_stuff()
> ...
> >>> main()
> a Opened
> b Opened
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 3, in main
> AttributeError: 'C' object has no attribute 'do_stuff'
> >>>
>  
> Uhh I'm not seeing any messages about the files getting closed.

Then that is indeed a challenge. From CPython back in 2.6 days up to 
Python36-32 what I see is:-

a Opened
b Opened
Traceback (most recent call last):
...
AttributeError: 'C' object has no attribute 'dostuff'
a Closed
b Closed

> Maybe exceptions aren't as easy to handle as you think? 

Well there is a general issue with exceptions owing to the ease
with which one can create cycles that may catch out newbs. But
that is not the case here.

> Or maybe you
> just haven't tried any of this (which is obvious from the bug in your
> code 

Or maybe I just made a typo when simplifying my test case and failed to retest?

Here is my fixed case, if someone else could try it in CPython and report back 
that would be interesting:-

class RAIIFileAccess():
def __init__(self, fname):
print("%s Opened" % fname)
self.fname = fname

def __del__(self):
print("%s Closed" % self.fname)

class A():
def __init__(self):
self.res = RAIIFileAccess("a")

class B():
def __init__(self):
self.res = RAIIFileAccess("b")

class C():
def __init__(self):
self.a = A()
self.b = B()

def main():
c = C()
c.dostuff()

main()

> You keep insisting that this is an easy thing.  > We keep pointing out
> that it isn't. Now you're proving that you haven't even attempted any
> of this. 

Nonsense. But you have got a result I have never seen in many years 
and I would like to get to the  bottom of it.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Sunday, 4 March 2018 23:56:09 UTC, Chris Angelico  wrote:
> On Sun, Mar 4, 2018 at 10:37 PM, Ooomzay  wrote:
> > Please consider the case of a composite resource: You need to implement
> > __enter__, __exit__ and track the open/closed state at every level in
> > your component hierarchy - even if some levels hold no resources directly.
> >
> > This is burdensome, breaks encapsulation, breaks invariance and is error 
> > prone
> > ...very unpythonic.
> 
> Why do you need to? I don't understand your complaint here - can you
> give an example of a composite resource that needs this kind of
> special management?

Here is an example of a composite resource using RAII:- 

class RAIIFileAccess(): 
def __init__(self, fname): 
print("%s Opened" % fname) 
def __del__(self): 
print("%s Closed" % fname) 

class A(): 
def __init__(self): 
self.res = RAIIFileAccess("a") 

class B(): 
def __init__(self): 
self.res = RAIIFileAccess("b") 

class C(): 
def __init__(self): 
self.a = A() 
self.b = B() 
  
def main(): 
c = C() 

Under this PEP this is all that is needed to guarantee that the files "a" 
and "b" are closed on exit from main or after any exception has been handled. 

Also note that if you have a reference to these objects then they are 
guaranteed to be in a valid/useable/open state (invariant) - no danger 
or need to worry/check about enter/exit state. 

Now repeat this exercise with "with".
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-05 Thread Ooomzay
On Monday, March 5, 2018 at 6:38:49 AM UTC, Mark Lawrence wrote:
> On 05/03/18 01:01, Ooomzay wrote:
> > On Sunday, 4 March 2018 23:57:24 UTC, Mark Lawrence  wrote:
> >> On 04/03/18 02:28, Ooomzay wrote:
> >>> On Friday, 2 March 2018 15:37:25 UTC, Paul  Moore  wrote:
> >>> [snip]
> >>>>   def fn():
> >>>>   for i in range(1):
> >>>>   with open(f"file{i}.txt", "w") as f:
> >>>>   f.write("Some text")
> >>>>
> >>>> How would you write this in your RAII style - without leaving 10,000
> >>>> file descriptors open until the end of the function?
> >>>
> >>>   def fn():
> >>>   for i in range(1):
> >>>   f = RAIIFile(f"file{i}.txt", "w")
> >>>   f.write("Some text")
> >>>
> > 
> >> Over my dead body.
> > 
> > Care to expand on that?
> > 
> 
> Sure, when you state what you intend doing about reference cycles, which 
> you've been asked about countless times.

Nothing. No change whatever. As I stated in my second post ref cycles are 
orthogonal to this PEP. 

If you want to use RAII objects then you will make sure you avoid adding them 
to orphan cycles by design. If you don't know how to do that then don't write 
applications that manage critical resources.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Monday, 5 March 2018 01:11:43 UTC, Richard Damon  wrote:
> On 3/4/18 6:55 PM, Ned Batchelder wrote:
> > On 3/4/18 5:25 PM, Ooomzay wrote:
> >> On Sunday, 4 March 2018 14:37:30 UTC, Ned Batchelder  wrote:
> >>> Are you including cyclic references in your assertion that CPython
> >>> behaves as you want?
> >> Yes. Because the only behaviour required for RAII is to detect and 
> >> debug such cycles in order to eliminate them. It is a design 
> >> error/resource leak to create an orphan cycle containing RAII objects.
> >>
> >> def main():
> >> gc,disable
> >>
> >>
> >>
> >
> > This isn't a reasonable position.  Cycles exist, and the gc exists for 
> > a reason.  Your proposal isn't going to go anywhere if you just 
> > naively ignore cycles.
> >
> > --Ned.
> 
> While Ooomzay seems to want to say that all cycles are bad, 

I only want to say that orphan cycles with RAII objects in them are bad. 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Saturday, 3 March 2018 17:10:53 UTC, Dietmar Schwertberger  wrote:
> CPython does *not* guarantee destruction when the object reference goes 
> out of scope, even if there are no other references.
> I would very much appreciate such a deterministic behaviour, at least 
> with CPython.
> 
> I recently had to debug an issue in the matplotlib wx backend (*). Under 
> certain conditions, the wx device context was not destroyed when the 
> reference went out of scope. Adding a del to the end of the method or 
> calling the Destroy method of the context did fix the issue. (There was 
> also a hidden reference, but avoiding this was not sufficient. The del 
> was still required.)

You say the reference was out of scope but that a del was still required. What 
were you delling if the reference was out of scope? Could you sketch the code.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 23:55:33 UTC, Ned Batchelder  wrote:
> On 3/4/18 5:25 PM, Ooomzay wrote:
> > On Sunday, 4 March 2018 14:37:30 UTC, Ned Batchelder  wrote:
> >> Are you including cyclic references in your assertion that CPython
> >> behaves as you want?
> > Yes. Because the only behaviour required for RAII is to detect and debug 
> > such cycles in order to eliminate them. It is a design error/resource leak 
> > to create an orphan cycle containing RAII objects.
> >
> This isn't a reasonable position.  Cycles exist, and the gc exists for a 
> reason.  Your proposal isn't going to go anywhere if you just naively 
> ignore cycles.

I am not naively ignoring them. But _if_ you want to use RAII then do not leak 
them in cycles. Put anything else in there you like and gc them as before.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 23:57:24 UTC, Mark Lawrence  wrote:
> On 04/03/18 02:28, Ooomzay wrote:
> > On Friday, 2 March 2018 15:37:25 UTC, Paul  Moore  wrote:
> > [snip]
> >>  def fn():
> >>  for i in range(1):
> >>  with open(f"file{i}.txt", "w") as f:
> >>  f.write("Some text")
> >>
> >> How would you write this in your RAII style - without leaving 10,000
> >> file descriptors open until the end of the function?
> >   
> >  def fn():
> >  for i in range(1):
> >  f = RAIIFile(f"file{i}.txt", "w")
> >  f.write("Some text")
> > 

> Over my dead body.  

Care to expand on that?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 15:24:08 UTC, Steven D'Aprano  wrote:
> On Sun, 04 Mar 2018 03:37:38 -0800, Ooomzay wrote:
> 
> > Please consider the case of a composite resource: You need to implement
> > __enter__, __exit__ and track the open/closed state at every level in
> > your component hierarchy - even if some levels hold no resources
> > directly.
> > This is burdensome, breaks encapsulation, breaks invariance and is error
> > prone ...very unpythonic.
> 
> Without a more concrete example, I cannot comment on these claims.

Here is an example of a composite resource using RAII:-

class RAIIFileAccess():
def __init__(self, fname):
print("%s Opened" % fname)
def __del__(self):
print("%s Closed" % fname)

class A():
def __init__(self):
self.res = RAIIFileAccess("a") 

class B():
def __init__(self):
self.res = RAIIFileAccess("b")

class C():
def __init__(self):
self.a = A()
self.b = B()
 
def main():
c = C()

Under this PEP this is all that is needed to guarantee that the files "a" 
and "b" are closed on exit from main or after any exception has been handled.

Also note that if you have a reference to these objects then they are 
guaranteed to be in a valid/useable/open state (invariant) - no danger
or need to worry/check about enter/exit state.

Now repeat this example with "with".

> [...]
> > My PEP is about improving the linguistic integrity and fitness for
> > resource management purpose of the language.
> 
> So you claim, but *requiring* reference counting semantics does not 
> improve the integrity or fitness of the language. 

We will just have to disagree on that for now.

> And the required 
> changes to programming styles and practices (no cycles, 

No change required. But if you _choose_ to benefit from RAII you had better 
not create orphan cycles with RAII objects in them, as that 
is clearly a resource leak.

> no globals, 

No change required. But if you _choose_ to benefit from RAII you had better 
take care to delete any RAII resources you choose to hold at global scope in 
a robust way. (These are exceptional in my experience).

> put all resources inside their own scope) 

No change required. But if you _choose_ to benefit from RAII you can make use
of python's existing scopes (functions) or del to restrict resource lifetimes.

> >> In any case, you might not like with statements, but I think they're
> >> infinitely better than:
> >> 
> >> def meaningless_function_that_exists_only_to_manage_resource():
> >> x = open_resource()
> >> process(x)
> > 
> >> def function():
> >> meaningless_function_that_exists_only_to_manage_resource()
> >> sleep(1)  # simulate a long-running function
> > 
> > Why would you prefer a new construct?
> 
> I don't prefer a new construct. The "with" statement isn't "new". It goes 
> back to Python 2.5 (`from __future__ import with_statement`) which is 
> more than eleven years old now. That's about half the lifetime of the 
> language!
> 
> I prefer the with statement because it is *explicit*, simple to use, and 
> clear to read. I can read some code and instantly see that when the with 
> block ends, the resource will be closed, regardless of how many 
> references to the object still exist.
> 
> I don't have to try to predict (guess!) when the last reference will go 
> out of scope, because that's irrelevant.

If you don't care about what the other references might be then 
RAII is not for you. Fine.
 
> RAII conflates the lifetime of the object with the lifetime of the 
> resource held by the object. 

This "conflation" is called "invariance" and is usually considered a 
"very good thing" as you cant have references floating around to
half-baked resources.

> They are not the same, and the object can 
> outlive the resource.

Not with RAII it can't. Simple. Good. 

> Your position is:
> 
> "RAII makes it really elegant to close the file! All you need to do is 
> make sure that when you want to close the file, you delete all the 
> references to the file, so that it goes out of scope, and the file will 
> be closed."
> 
> My position is:
> 
> "If I want to close the file, I'll just close the file. Why should I care 
> that there are zero or one or a million references to it?"

Because if you have no idea what references there are you can not assume it 
is OK to close the file! That would be a truly terrible program design.

> >> - the with block is equivalent to a try...finally, and so it is
> >>   guaranteed to close the resourc

Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 14:37:30 UTC, Ned Batchelder  wrote:
> Are you including cyclic references in your assertion that CPython 
> behaves as you want?

Yes. Because the only behaviour required for RAII is to detect and debug such 
cycles in order to eliminate them. It is a design error/resource leak to create 
an orphan cycle containing RAII objects.

def main():
gc,disable



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 03:00:13 UTC, Chris Angelico  wrote:
> This thread is dead. The OP wants to wave a magic wand and say
> "__del__ is now guaranteed to be called immediately", 

No "magic" required: Just one line change in the language reference will do it.

> without any explanation

The PEP says it all really: To make the very pythonic RAII idiom available in 
python.

> - and, from the look of things, without any understanding
> - of what that means for the language 

What impact on the _language_ (c.f. interpreter) do you think I have not 
understood?

It is is 100% backwards compatible with the language. It breaks nothing.

It allows people who want to use the RAII idiom to do so.

It allows people who want to use the "with" idiom to continue do so.

> and the interpreters. 

I am well aware of what it will mean for interpreters. For some interpreters it 
will have zero impact (e.g. CPython) and for some others it would unlikely be 
economic to make them comply.

The decision here is does python want to be more pythonic, and make itself 
attractive for resource management applications or does it want to be 
compromised by some implementations?

> Everyone else is saying "your magic wand is broken". This is not going to go
> anywhere.

Well I see a lot of posts that indicate peeps here are more comfortable with 
the "with" idiom than the RAII idiom but I have not yet seen a single 
linguistic problem or breakage.

As it happens I have used RAII extensively with CPython to manage a debugging 
environment with complex external resources that need managing very 
efficiently. 

(I would use C++ if starting from scratch because it _guarantees_ the required 
deterministic destruction whereas python does not)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 03:16:31 UTC, Paul Rubin  wrote:
> Chris Angelico  writes:
> > Yep, cool. Now do that with all of your smart pointers being on the
> > heap too. You are not allowed to use ANY stack objects.  ANY. Got it?
> 
> That's both overconstraining and not even that big a problem the way you
> phrase it.
> 
> 1) Python has both the "with" statement and try/finally.  Both of these
> run code at the exit from a syntactically defined scope.  So they are
> like stack allocation in C++, where a deallocator can run when the scope
> exits.
> 
> 2) Even with no scope-based de-allocation, it's common to put smart
> pointers into containers like lists and vectors.  So you could have a
> unique_ptr to a filestream object, and stash the unique_ptr someplace as
> a vector element, where the vector itself could be part of some even
> more deeply nested structure.  At some point, the big structure gets
> deleted (maybe through a manually-executed delete statement).  When that
> happens, if the nested structures are all standard containers full of
> unique_ptrs, the top-level finalizer will end up traversing the entire
> tree and freeing up the file handles and whatever else might be in
> there.
> 
> It occurs to me, maybe #2 above is closer to what the OP is really after
> in Python.  

Yep. C++ smart pointers are a good analogue to python references for 
purposes of this PEP.

> I guess it's doable, but refcounts don't seem like the right
> way. 

Well refcounts are definitely "doable": This is how the reference python 
implementation, CPython, currently manages to comply with this PEP and can 
therefore be used for RAII.

This PEP is an attempt to _guarantee_ this behaviour and make the elegance 
of RAII available to all pythonistas that want it. Without this guarantee 
python is not attractive to applications that must manage non-trivial 
resources reliably.

Aside: I once read somewhere that must have seemed authoritative at the
time, that CPython _guarantees_ to continue to behave like this - but now the 
subject is topical again I can find no trace of this guarantee.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 04:23:07 UTC, Steven D'Aprano  wrote:
> [...]
> [This PEP] imposes enormous burdens on the maintainers of at least five 
> interpreters (CPython, Stackless, Jython, IronPython, PyPy) all of which 
> will need to be re-written to have RAII semantics guaranteed; 

Not so:-  CPython, the reference interpreter, already implements the required 
behaviour, as mentioned in the PEP.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-04 Thread Ooomzay
On Sunday, 4 March 2018 04:23:07 UTC, Steven D'Aprano  wrote:
> On Sat, 03 Mar 2018 18:19:37 -0800, Ooomzay wrote:
> 
> >> def function():
> >> x = open_resource()
> >> process(x)
> >> # and we're done with x now, but too lazy to explicitly close it
> >> sleep(1) # Simulate some more work. Lots of work. 
> >> return
> >> # and finally x is closed (2.8 hours after you finished using it)
> >> 
> >> The answer in C++ is "well don't do that then". The answer is Python
> >> is, "don't be so lazy, just use a with statement".
> > 
> > The answer in C++ would be to say "don't be so lazy just put the x
> > manipulation in a function or sub-block". 
> 
> Right -- so you still have to think about resource management. The 
> premise of this proposal is that RAII means you don't have to think about 
> resource management, it just happens, but that's not really the case.

That is not my main premise: Which is that RAII is a more elegant (no 
specialised syntax at all) and robust way to manage resources.

Please consider the case of a composite resource: You need to implement
__enter__, __exit__ and track the open/closed state at every level in
your component hierarchy - even if some levels hold no resources directly.

This is burdensome, breaks encapsulation, breaks invariance and is error prone
...very unpythonic.

> > The answer with Python + this
> > PEP would be "don't be so lazy just put the x manipulation in a function
> > or explicitly del x" ...no new syntax.
> 
> Sure -- but it doesn't gain you anything we don't already have.

See above.
 
> It imposes enormous burdens on the maintainers of at least five 
> interpreters (CPython, Stackless, Jython, IronPython, PyPy) all of which 
> will need to be re-written to have RAII semantics guaranteed; 

Yes. This is a substantial issue that will almost certainly see it rejected by 
HWCNBN on political, rather than linguistic, grounds.

My PEP is about improving the linguistic integrity and fitness for resource 
management purpose of the language.

> it will 
> probably have significant performance costs; and at the end of the day, 
> the benefit over using a with statement is minor.
> 
> (Actually, I'm not convinced that there is *any* benefit. If anything, I 
> think it will be a reliability regression -- see below.)
> 
> >> If you want deterministic closing of resources, with statements are the
> >> way to do it.
> >> 
> >> def function():
> >> with open_resource() as x:
> >> process(x)
> >> # and x is guaranteed to be closed
> > 
> > What a palava!
> 
> I don't know that word, and neither do any of my dictionaries. I think 
> the word you might mean is "pelaver"?

I don't know that word, and neither do any of my dictionaries. I think 
the word you might mean is "Palaver"? 

Anyway Palava/Pelaver/Palaver/Palavra/Palabra derives from the word 
for "word", but in England it is often used idiomatically to mean a 
surfeit of words, or even more generally, a surfeit of effort.

I intend it in both senses: The unnecessary addition of 
the words "with", "as", "__enter__" & "__exit__" to the language 
and the need implement the latter two methods all 
over the place.

> In any case, you might not like with statements, but I think they're 
> infinitely better than:
> 
> def meaningless_function_that_exists_only_to_manage_resource():
> x = open_resource()
> process(x)

> def function():
> meaningless_function_that_exists_only_to_manage_resource()
> sleep(1)  # simulate a long-running function

Why would you prefer a new construct? Functions _are_ pythons scoping context! 
Giving one a pejorative name does not change that. 
 
> In other words, your solutions are just as much manual resource 
> management as the with statement. The only differences are:
> 
> - instead of explicitly using a dedicated syntax designed for 
>   resource management, you're implicitly using scope behaviour;

Excellent: With the benefit of automatic, exception safe, destruction of 
resources, including composite resources.
 
> - the with block is equivalent to a try...finally, and so it is
>   guaranteed to close the resource even if an exception occurs;
>   your solution isn't.

> If process(x) creates a non-local reference to x, and then raises an 
> exception, and that exception is caught elsewhere, x will not go out of 
> scope and won't be closed. 
> A regression in the reliability of the code.

This PEP does not affect existing code. Peeps who are familiar with RAII
understand that creating a global r

Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread Ooomzay
On Sunday, 4 March 2018 01:58:02 UTC, Gregory Ewing  wrote:
> ooomzay wrote:
> > Well he was not telling you the whole story: RAII works just as well with
> > heap objects using smart pointers (unique_ptr and friends) which are a 
> > closer
> > analogy to python object references.
> 
> By that definition, *all* resource management in Python is
> based on RAII[1]. 

I think not. Objects may have a close() in their __del__ method as a back-up - 
but currently this is not guaranteed to be called in a timely fashion. Hence 
the 
justification for "with" and my proposal to obviate it by actually guaranteeing 
that __del__ is always called in a timely fashion.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread Ooomzay
On Friday, 2 March 2018 15:37:25 UTC, Paul  Moore  wrote:
[snip]
> def fn():
> for i in range(1):
> with open(f"file{i}.txt", "w") as f:
> f.write("Some text")
> 
> How would you write this in your RAII style - without leaving 10,000
> file descriptors open until the end of the function?
 
def fn():
for i in range(1):
f = RAIIFile(f"file{i}.txt", "w")
f.write("Some text")
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread Ooomzay
On Saturday, 3 March 2018 23:52:34 UTC, Steven D'Aprano  wrote:
> I know that laziness and hubris are programmer virtues, but there is 
> still such a thing as *too much laziness*. RAII works in C++ where 
> instances are allocated in the stack, but even there, if you have an 
> especially long-lived function, your resources won't be closed promptly. 
> In Python terms:
> 
> def function():
> x = open_resource()
> process(x)
> # and we're done with x now, but too lazy to explicitly close it
> sleep(1) # Simulate some more work. Lots of work.
> return
> # and finally x is closed (2.8 hours after you finished using it)
> 
> The answer in C++ is "well don't do that then". The answer is Python is, 
> "don't be so lazy, just use a with statement".

The answer in C++ would be to say "don't be so lazy just put the x 
manipulation in a function or sub-block". The answer with Python + this PEP 
would be "don't be so lazy just put the x manipulation in a function or 
explicitly del x" ...no new syntax.

> If you want deterministic closing of resources, with statements are the 
> way to do it.
> 
> def function():
> with open_resource() as x:
> process(x)
> # and x is guaranteed to be closed

What a palava!

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread Ooomzay
On Saturday, 3 March 2018 17:44:08 UTC, Chris Angelico  wrote:
> On Sun, Mar 4, 2018 at 4:37 AM, Richard Damon  
> > Yes, stack allocated object in C++ have a nice lifetime to allow RAII to
> > work, but it doesn't just work with stack allocated objects. A lot of RAII
> > objects are members of a class object that may well be allocated on the
> > heap, and RAII makes sure that all the needed cleanup gets done when that
> > object gets destroyed.
> 
> How do you guarantee that the heap object is properly disposed of when
> you're done with it? Your RAII object depends 100% on the destruction
> of the heap object.

Smart pointers (unique_ptr and friends) are used to manage heap object 
lifecycles n . These are analogous to python object references.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread Ooomzay
On Saturday, 3 March 2018 17:16:14 UTC, Ned Batchelder  wrote:
> On 3/2/18 10:36 AM, Paul Moore wrote:
> > Or (real Python):
> >
> >  def fn():
> >  for i in range(1):
> >  with open(f"file{i}.txt", "w") as f:
> >  f.write("Some text")
> >
> > How would you write this in your RAII style - without leaving 10,000
> > file descriptors open until the end of the function?
> 
> IIUC, if the OP's proposal were accepted, the __del__ method would be 
> called as soon as the *value*'s reference count went to zero. That means 
> this wouldn't leave 10,000 files open, since each open() would assign a 
> new file object to f, which would make the previous file object's ref 
> count be zero, and it would be closed.

You have understood correctly. Here is the equivalent RAII version:-

def fn():
for i in range(1):
 f = RAIIFile(f"file{i}.txt", "w")
 f.write("Some text")

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread ooomzay
On Friday, March 2, 2018 at 5:29:54 AM UTC, Rustom Mody wrote:
> Please excuse if this has been addressed above and/or its too basic:
> What's the difference between RAII and python's with/context-managers?

They address the same problem but I am claiming that RAII achieves this in a 
significantly more elegant/pythonic way without involving any special keywords 
or methods. in summary _if_ the PEP was adopted and/or you are using CPython 
today then:-

def riaa_file_copy(srcname, dstname):
src = RAIIFile(srcname, 'r')
dst = RAIIFile(dstname, 'w')
for line in src:
dst.write(line)

becomes equivalent to:

def pep343_file_copy(srcname, dstname):
with open(srcname, 'r')  as src,
 open(dstname, 'w') as dst:
for line in src:
dst.write(line)

RAII resource management is also simpler to implement only requiring existing 
__init__ and __del__ methods (e.g. to open/close the underlying file) and the 
resource objects are invariant. Which means the objects/managers do not need to 
track the enter/exit state - as there is no way to access them when they are 
not "open" in RAII.





-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread ooomzay

On Friday, March 2, 2018 at 3:37:25 PM UTC, Paul  Moore wrote:
> [...]
> RAII works in C++ (where it was initially invented) because it's used
> with stack-allocated variables that have clearly-defined and limited
> scope. 

RAII also works with smart pointers, which are a closer analogue 
to python references.

> In my experience writing C++, nobody uses RAII with
> heap-allocated variables - those require explicit allocation and
> deallocation and so are equivalent to having an explicit "close()"
> method in Python (or using __del__ in CPython as it currently exists).

In my experience no-one has been been explicitly deallocating
heap-variables for many years: they have been using smart pointers 
and RAII.

> Python doesn't have stack allocation, nor does it have a deterministic
> order of deletion of objects when their last reference goes out of
> scope (which can happen simultaneously for many objects):
>
> class Tracker:
> def __init__(self, n):
> self.n = n
> def __del__(self):
> print("Deleting instance", self.n)
> 
> def f():
> a = Tracker(1)
> b = Tracker(2)
> 
> f()
> 
> The language doesn't guarantee that a is removed before b. Are you
> proposing to make that change to the language as well?

It would improve things more, but I have not included such a proposal
in the current PEP as this is not essential for the main benefit. 
 
> Also Python only has function scope, so variables local to a
> smaller-than-the-function block of code aren't possible. That's
> something that is used in C++ a lot to limit the lifetime of resources
> under RAII. How do you propose to address that (without needing
> explicit del statements)? 

Create a sub function. 

> That's why the with statement exists, to
> clearly define lifetimes smaller than "the enclosing function". 

It does that in a half-hearted and smelly way compared to a function: 
The object references are left dangling in a broken state (not invariant). 
In fact you would do well to wrap your "with"s in a function to contain 
the smell.

> Your proposal doesn't offer any equivalent (other than an extra function).

An equivalent is not needed. Using a function is the ideomatic and does not
leak - unlike the "with" hack. (IMO block-scoping would enhance the langauge
but is not essential so not in this PEP).

> Consider C++:
> 
> void fn() {
> for (i = 0; i < 1; ++i) {
> char name[100];
> sprintf(name, "file%d.txt, i);
> File f(name); // I don't think std::ofstream doesn't support RAII
> f << "Some text";
> }
> }
> 
> Or (real Python):
> 
> def fn():
> for i in range(1):
> with open(f"file{i}.txt", "w") as f:
> f.write("Some text")
> 
> How would you write this in your RAII style - without leaving 10,000
> file descriptors open until the end of the function?

 def write_some_text_to_file(fname):
  f = RAIIFileAccess(fname, 'w')
  f.write("Some text")

 def fn():
 for i in range(1):
 write_some_text_to_file(f"file{i}.txt")

> That's both less efficient (function calls have a cost) 

Oh come now. No one is choosing to use python for its efficiency and 
functions that deal with real resources, such as files, are likely 
dominated by the os fopen/close etc.

> and less maintainable than the with-statement version.

I disagree. Even for such a trivial example, as soon as you 
start to change the detail of what you do then the usual maintainability
benefits of small well factored functions comes into play. That's why we
have functions in the language isn't it? Or do you just write one 
long script?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread ooomzay
On Saturday, March 3, 2018 at 4:33:59 PM UTC, Michael Torrie wrote:
> On 03/03/2018 09:02 AM, ooomzay wrote:
> > 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. 
> 
> Sure but did you read what Paul Moore wrote?  

Yes.

> He said RAII works in C++
> because objects are allocated on the *stack* with strict lifetimes and
> scopes. 

Well he was not telling you the whole story: RAII works just as well with heap 
objects using smart pointers (unique_ptr and friends) which are a closer 
analogy to python object references.

> In C++, Heap-allocated objects must still be managed manually, without
> the benefit of RAII, 

No one should be manually managing resources on the heap in C++. They should be 
using smart pointers.

> for much of the same reasons as people are giving
> here for why RAII is not a good fit for Python.  

...for much the same reasons I am giving here for why RAII could 
be a very good fit for python.

> There are smart pointer
> objects that try to give RAII semantics to heap-allocated objects, with
> varying degrees of success. In other words there are some limitations.

Not sure what limitations you are evoking here but I have not had to write a 
delete or suffered a resource leak in C++ for many years. (we rolled our own 
smart pointers before they were standardised).

> Python does not have stack-allocated objects, so the same issues that
> prevent RAII from automatically applying in C++ to heap objects exist here.

False premise, false conclusion.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-03 Thread ooomzay
On Friday, March 2, 2018 at 10:43:57 PM UTC, Steven D'Aprano wrote:
> On Fri, 02 Mar 2018 07:09:19 -0800, ooomzay wrote:
> [...]
> >> If you're going to *require* the programmer to explicitly del the
> >> reference:
> >>
> >> f = open("file")
> >> text = f.read()
> >> del f
> > 
> > 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. Can you give an example of how 
this might happen? (Apart from writing leaky exception handlers, which I 
trust no one thinks is a good idea)

> [...]
> Your justification for requiring RAII is to ensure the timely closure of 
> resources -- but to do that, you have to explicitly close or delete the 
> resource. It simply isn't true that "RAII frees the programmer from even 
> having to remember to close the file".

In the special case (keyword global) that you reference resources from global 
scope - then yes, you must remember to del the global references before you 
exit to avoid relying on the vagaries of exit processing.

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.

> >> then you might as well require them to explicitly close the file:
> >> 
> >> f = open("file")
> >> text = f.read()
> >> f.close()
> >> 
> >> which we know from many years experience is not satisfactory except for
> >> the simplest scripts that don't need to care about resource management.
> >> That's the fatal flaw in RAII:
> > 
> > We must be discussing a different RAII. That is the raison d'etre of
> > RAII: RAII directly addresses this problem in an exception-safe way that
> > does not burden the resource user at all.
> 
> 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.

> 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. 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-02 Thread ooomzay
On Friday, March 2, 2018 at 2:43:09 PM UTC, Chris Angelico wrote:
> On Sat, Mar 3, 2018 at 1:18 AM,  ooomzay wrote:
> > On Friday, March 2, 2018 at 8:16:22 AM UTC, Paul Rubin wrote:[snip]
> >> controlling stuff like file handles
> >> with scopes (like with "with") is fine.
> >
> > How does with work for non-trivial/composite objects that 
> > represent/reference multiple resources or even a hierarchy of such objects 
> > where all the resources held must be released in a timely fashion when 
> > finished with?
> >
> 
> Can you give me an example that works with RAII but doesn't work in a
> 'with' statement?

My claim is about the relative elegance/pythonic nature of RAII w.r.t. 'with'. 
Probably with enough coding and no ommissions or mistakes 'with' could do 
achieve the same result that RAII does automatically without any 
burden on the user.

Consider the hierarchy/tree of resource-holding objects postulated above... 
Presumably __enter__, __exit__ (or functional equivalent) would have to be 
implemented at every layer breaking the invariance. Thus complicating and 
making less robust every object it touches.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-02 Thread ooomzay
On Friday, March 2, 2018 at 4:35:41 AM UTC, Steven D'Aprano wrote:
> On Thu, 01 Mar 2018 16:26:47 -0800, ooomzay wrote:
> 
> >> >> When does the destination file get closed?
> >> >
> >> > When you execute:-
> >> >
> >> >del dst
> >> >
> >> > or:-
> >> >
> >> >dst = something_else
> >> 
> >> What if you don't?
> > 
> > Then the resource will remain open until your script exits at which
> > point it is probably not very well defined exactly when or even if the
> > destructor/__del__ will be called.
> > 
> > I.e. Don't do this! Did you have some realistic case in mind or are you
> > just probing the behaviour?
> 
> 
> If you're going to *require* the programmer to explicitly del the 
> reference:
>
> f = open("file")
> text = f.read()
> del f

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. 

In practice CPython destroys it cleanly on exit - but I am not sure the 
language guarantees this - in any case RAII won't make things any worse in this 
respect. (Logfiles are a common example of such global resource.)

> then you might as well require them to explicitly close the file:
> 
> f = open("file")
> text = f.read()
> f.close()
> 
> which we know from many years experience is not satisfactory except for 
> the simplest scripts that don't need to care about resource management.
> That's the fatal flaw in RAII: 

We must be discussing a different RAII. That is the raison d'etre of RAII: RAII 
directly addresses this problem in an exception-safe way that does not burden 
the resource user at all.

> the problem is that the lifespan of the resource may 
> not be the same as the lifetime of the object. 
>
> Especially for files, the 
> problem is that the lifespan of resource (the time you are actually using 
> it) may be significantly less than the lifespan of the object holding 
> onto that resource. Since there's no way for the interpreter to know 
> whether or not you have finished with the resource, you have a choice:
> 
> - close the resource yourself (either explicitly with file.close(), 
>   or implicitly with a context manager);
> 
> - or keep the resource open indefinitely, until such eventual time
>   that the object is garbage collected and the resource closed.

Hence my PEP! It enables RAII. The interpreter merely has to call __del__ as 
soon as the object is no longer referenced (as does CPYthon).
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction (Posting On Python-List Prohibited)

2018-03-02 Thread ooomzay
On Friday, March 2, 2018 at 1:59:02 AM UTC, Lawrence D’Oliveiro wrote:
> On Friday, March 2, 2018 at 1:03:08 PM UTC+13, ooo...@gmail.com wrote:
> > On Thursday, March 1, 2018 at 11:51:50 PM UTC, Lawrence D’Oliveiro wrote:
> >> On Friday, March 2, 2018 at 12:39:01 PM UTC+13, ooo...@gmail.com wrote:
> >>>
> >>> class RAIIFileAccess():
> >>> '''File Access-like Resource using [RAII] idiom'''
> >>> ...
> >>> def __del__(self):
> >>> low_level_file_close(self.handle) # fictitious function
> >> 
> >> This may be OK for files opening for reading, not so good for writing.
> > 
> > Please could you explain the issue you perceive with writing?
> 
> Compare the difference in behaviour between
> 
> f = open("/dev/full", "w")
> f.write("junk")
> f.close()
> 
> and
> 
> f = open("/dev/full", "w")
> f.write("junk")
> f = None
> 
> Should there be a difference in behaviour?

Could you please be very explicit about why you think the PEP would be more 
suitable when reading a file than when writing a file? You have responded with 
another question that I just can't see the relevance of (yet).
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-02 Thread ooomzay
On Friday, March 2, 2018 at 8:16:22 AM UTC, Paul Rubin wrote:[snip]
> controlling stuff like file handles
> with scopes (like with "with") is fine.

How does with work for non-trivial/composite objects that represent/reference 
multiple resources or even a hierarchy of such objects where all the resources 
held must be released in a timely fashion when finished with?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-02 Thread ooomzay
On Friday, March 2, 2018 at 12:22:13 AM UTC, MRAB wrote:
> On 2018-03-01 23:38, ooomzay wrote:
[Snip]
> > PEP343 requires two new methods: __enter__ & __exit__.
> > RIAA requires no new methods.
> >
> > RIAA resources are invariant: If you have a reference to it you can use it.
> > PEP343 resources can not be invariant: To be robust the enter/exit state
> > must be tracked and checked. (assert self.handle in the example)
[Snip]
> > PEP343 requires specialised "with" syntax, RIAA requires no new syntax.
> > Furthermore, although src & dst objects are still accessible outside the
> > PEP343 "with" block they are not in a usable state (not invariant).
> > 
> > In the RIAA case the resources are guaranteed to be in a usable state as 
> > long
> > as any reference exists (invariant). References can also be safely
> > passed around.The resource will be freed/closed when the last man has 
> > finished
> > with it, even in the face of exceptions.
> > [snip]
> >
> What's the difference between 'RAIIFileAccess' and 'open'?

I listed all the differences I know of in my preceding post. (I have snipped 
the other stuff so they are easy to see).
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-01 Thread ooomzay
On Friday, March 2, 2018 at 12:14:53 AM UTC, Chris Angelico wrote:
> On Fri, Mar 2, 2018 at 11:07 AM,  ooomzay wrote:
> > On Thursday, March 1, 2018 at 11:59:26 PM UTC, Chris Angelico wrote:
> >> On Fri, Mar 2, 2018 at 10:38 AM,  ooomzay wrote:
> >> > def raii_example():
> >> >
> >> > src = RAIIFileAccess("src.txt", 'r')
> >> > dst = RAIIFileAccess("dst.txt", 'w')
> >> >
> >> > for line in src:
> >> > dst.write(line)
> >>
> >> What happens if we make this change?
> >>
> >> def raii_example():
> >> global dst
> >> src = RAIIFileAccess("src.txt", 'r')
> >> dst = RAIIFileAccess("dst.txt", 'w')
> >>
> >> for line in src:
> >> dst.write(line)
> >>
> >> When does the destination file get closed?
> >
> > When you execute:-
> >
> >del dst
> >
> > or:-
> >
> >dst = something_else
> 
> What if you don't?

Then the resource will remain open until your script exits at which point it is 
probably not very well defined exactly when or even if the destructor/__del__ 
will be called.

I.e. Don't do this! Did you have some realistic case in mind or are you just 
probing the behaviour?


-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-01 Thread ooomzay
On Thursday, March 1, 2018 at 11:59:26 PM UTC, Chris Angelico wrote:
> On Fri, Mar 2, 2018 at 10:38 AM,  ooomzay wrote:
> > def raii_example():
> >
> > src = RAIIFileAccess("src.txt", 'r')
> > dst = RAIIFileAccess("dst.txt", 'w')
> >
> > for line in src:
> > dst.write(line)
> 
> What happens if we make this change?
> 
> def raii_example():
> global dst
> src = RAIIFileAccess("src.txt", 'r')
> dst = RAIIFileAccess("dst.txt", 'w')
> 
> for line in src:
> dst.write(line)
> 
> When does the destination file get closed?

When you execute:-

   del dst

or:-

   dst = something_else

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction (Posting On Python-List Prohibited)

2018-03-01 Thread ooomzay
On Thursday, March 1, 2018 at 11:51:50 PM UTC, Lawrence D’Oliveiro wrote:
> On Friday, March 2, 2018 at 12:39:01 PM UTC+13, ooo...@gmail.com wrote:
> > class RAIIFileAccess():
> > '''File Access-like Resource using [RAII] idiom'''
> >
> > ...
> > 
> > def __del__(self):
> > low_level_file_close(self.handle) # fictitious function
> 
> This may be OK for files opening for reading, not so good for writing.

Please could you explain the issue you perceive with writing?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-01 Thread ooomzay
On Thursday, March 1, 2018 at 12:15:57 AM UTC, Paul Rubin wrote:
> RAII is similar to Python's "with" statement.  So it sounds like OP
> wants to replace one "malignant carbuncle" with another one.  

I would like to understand why you think RAII is not substantially more 
pythonic than "With". Below I have sketched out a File-like resource 
management scenario using both PEP343 and RAII idioms for comparison. 

First lets look at the implementation of the competing resource management 
classes:-


class PEP343FileAccess():
'''
A File Access-like resource with self-contained Context Manager for use 
with "with".

This could be acheived with two separate classes but I don't think that 
adds anything except lines of code.
'''

# Structors

def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.handle = None
# dummy file content accessible only when handle is not None
self.lines = ['one', 'two', 'three'] 

# PEP343 Context Manager compliance

def __enter__(self):
self.handle = low_level_file_open(self.filename, self.mode) # fictitious
return self

def __exit__(self, extype, exvalue, extraceback):
low_level_file_close(self.handle) # fictitious function
self.handle = None

# Example methods

def __iter__(self):
assert self.handle, "File has been closed"
for line in self.lines: 
yield line

def write(self, line):
assert self.handle, "File has been closed"
self.lines.append(line)


class RAIIFileAccess():
'''File Access-like Resource using RIAA idiom'''

# Structors

def __init__(self, filename, mode):
self.handle = low_level_file_open(filename, mode) # fictitious
# dummy content accessible as long as the object exists (invariant)
self.lines = ['one', 'two', 'three'] 

def __del__(self):
low_level_file_close(self.handle) # fictitious function

# Example methods

def __iter__(self):
for line in self.lines:
yield line

def write(self, line):
self.lines.append(line)


What I see is that PEP343 requires two new methods: __enter__ & __exit__.
RIAA requires no new methods.

RIAA resources are invariant: If you have a reference to it you can use it.

PEP343 resources can not be invariant: To be robust the enter/exit state
must be tracked and checked. (assert self.handle in the example)

Now lets look at example resource usage:-


def pep343_example():

with PEP343FileAccess("src.txt", 'r') as src, 
 PEP343FileAccess("dst.txt", 'w') as dst:

for line in src: 
dst.write(line)

def raii_example():

src = RAIIFileAccess("src.txt", 'r')
dst = RAIIFileAccess("dst.txt", 'w')

for line in src:
dst.write(line)


PEP343 requires specialised "with" syntax, RIAA requires no new syntax.

Furthermore, although src & dst objects are still accessible outside the 
PEP343 "with" block they are not in a usable state (not invariant).

In the RIAA case the resources are guaranteed to be in a usable state as long 
as any reference exists (invariant). References can also be safely
passed around.The resource will be freed/closed when the last man has finished 
with it, even in the face of exceptions.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-03-01 Thread ooomzay
On Thursday, March 1, 2018 at 12:35:38 PM UTC, Richard Damon wrote:
> [snip]
> I disagree with the original complaint that these 
> are always 'errors', if you know you have garbage collection, the 
> allowance of cycles knowing they will still get cleaned up is a useful 
> simplification if you don't need the immediate clean up.

I (O.P.) regret making that complaint, it was flippant and has distracted from 
the essence of the PEP. Whilst my informal introduction was deliberately a 
little provocative, my PEP is sincere and does not affect the ability to create 
orphan cycles.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-02-28 Thread ooomzay
On Wednesday, February 28, 2018 at 11:45:24 PM UTC, ooo...@gmail.com wrote:
> On Wednesday, February 28, 2018 at 11:02:17 PM UTC, Chris Angelico wrote:
> > On Thu, Mar 1, 2018 at 9:51 AM,  ooomzay wrote:
> > [snip]
> > Taking a really simple situation:
> > 
> > class Foo:
> > def __init__(self):
> > self.self = self
> > print("Creating a Foo")
> > def __del__(self):
> > print("Disposing of a Foo")
> > 
> > foo = Foo()
> > foo = 1
> > 
> > When do you expect __del__ to be called? 
> 
> At the point of (re)assignment: "foo = 1"

Oh... I now see there is a (non-weak) self reference in there.

So in this case it would be orphaned. It is a design error and should be 
recoded. I don't care how it is detected for current purposes.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: RFC: Proposal: Deterministic Object Destruction

2018-02-28 Thread ooomzay
On Wednesday, February 28, 2018 at 11:02:17 PM UTC, Chris Angelico wrote:
> On Thu, Mar 1, 2018 at 9:51 AM,  ooomzay wrote:
> > Specification
> > =
> >
> > When the last reference to an object goes out of scope the intepreter must 
> > synchronously, in the thread that releases the last reference, invoke the 
> > object's __del__() method and then free the memory occupied by that object.
> >
> 
> If it were that simple, why do you think it isn't currently mandated?

We know the implementation is feasible because CPython, the reference 
interpreter implementation, already does this. I am guessing that there is a 
lobby from garbage platforms where it would be harder to implement and 
integrate however the object of this proposal is the integrity of the language, 
not on making it easier to implement using garbage platforms.


> Here's one example: reference cycles. When do they get detected?

Orphan cycle _detection_ is orthogonal to this proposal. As cycles are always a 
symptom of a design error I personally have little interest in them other than 
some facility to detect/debug and eliminate them from applications by design 
(another topic).


> Taking a really simple situation:
> 
> class Foo:
> def __init__(self):
> self.self = self
> print("Creating a Foo")
> def __del__(self):
> print("Disposing of a Foo")
> 
> foo = Foo()
> foo = 1
> 
> When do you expect __del__ to be called? 

At the point of (re)assignment: "foo = 1"


> How do you implement this efficiently and reliably?

CPython already has a reliable and reasonably efficient implementation based on 
reference counting.

-- 
https://mail.python.org/mailman/listinfo/python-list


RFC: Proposal: Deterministic Object Destruction

2018-02-28 Thread ooomzay
Informal Background
===

Python's lack of Deterministic Object Destruction semantics strikes me as very 
unpythonic. This state of affairs spawns lengthy diatribes on __del__(), a 
variety of specialised and onerous resource management solutions and malignant 
carbuncles such as PEP 343 (the "with" statement). None of these match the 
practical utility, simplicity, generality and robustness of Deterministic 
Object Destruction combined with the RAII idiom to manage resources.

I have therefore drafted the radical but simple and 100% backward compatible 
proposal below to remedy this situation and pave the way for numerous tidy ups 
(out of scope of this proposal).

I am now retiring to a safe distance and invite your comments on the PEP below:-


Abstract


This PEP proposes that valid python interpreters *must* synchronously destroy 
objects when the last reference to an object goes out of scope. This 
interpreter behaviour is currently permitted and exhibited by the reference 
implementation [CPython], but it is optional.

Motivation
==

To make the elegance (simplicity, generality, and robustness) of the "Resource 
Acquisition Is Initialization" (RAII) idiom available to all python 
applications and libraries.

To render less elegant and more onerous resource management solutions, such as 
the "with" Statement [PEP 343] obsolete.

Specification
=

When the last reference to an object goes out of scope the intepreter must 
synchronously, in the thread that releases the last reference, invoke the 
object's __del__() method and then free the memory occupied by that object.

Backwards Compatibility
===

This proposal preserves 100% backwards compatibility.

The language currently does not prescribe when, or even if, __del()__ will be 
called and object memory freed. Existing python applications and libraries can 
make no assumptions about this behaviour.

Reference Implementation


CPython

References
==

PEP 343 -- The "with" Statement
-- 
https://mail.python.org/mailman/listinfo/python-list