On 24 April 2013 05:59, anatoly techtonik <tech...@gmail.com> wrote:I truly hope it is not quite as you describe - otherwisew pySie would
> PySide Qt binding have an interesting property - when you create widgets,
> you need to assign them to variables. When such variable is lost, object is
> immediately destroyed.
be completly unusable.
What if one adds created objects to a list, instead of assigning them
to a variable?
Otherwiser, reference counting is usually enough in cPython to trigger
object destruction -
On Wed, Apr 24, 2013 at 12:23 PM, Ronald Oussoren <ronaldo...@mac.com> wrote:
The file is automaticly closed as soon as the file object is garbage collected. In your example CPython would currently collect at the end of the read call (unles there is an exception) because of the reference counting garbage collector, but other implementations have other garbage collectors and can collect the file object (much) later.
On 24 Apr, 2013, at 10:59, anatoly techtonik <tech...@gmail.com> wrote:
> Long time no see, all. :P
>
> PySide Qt binding have an interesting property - when you create widgets, you need to assign them to variables. When such variable is lost, object is immediately destroyed.
>
> I often use this one-shot code in setup.py:
> ...
> long_description = open('README.txt').read(),
> ....
>
> Which probably leaves the README.txt file open until the setup.py exits. So, the idea is to close the file as soon as the variable is lost.
>It was implemented a long time ago. The with statement was added because relying on automatic resource cleanup by a destructor might clean up the resource too late (for example because the file object is referenced by a local variable in a frame that's referenced by an exception).
> I don't know why it was not implemented in the first place. Any ideas?
>In python 3.3 and later you can use contexlib.ExitStack:
> Depending on the answer to the above, the solution can be different. I assume that this was done for a reason (probably immediate garbage collection is too expensive), but confirmation is welcome. Meanwhile the solution can be implemented with auto context manager, which __exit__ method is automatically called when all links to created object are lost.
>
> Difference from usual "with something" is that it is transparent to the user (leaves less details to worry about) and makes code more beautiful -- in the example above the assignment is made inside setup(...) parameter assignment. An example with ordinary "with" statement would look like:
>
> with open('README.txt') as readme:
> setup(
> ....
> long_description=readme.read(),
> ....
> )
with contextlib.ExitStack() as stack:
setup(
...
long_description = stack.enter_context(open('README.txt')).read(),
...
)
But for simple scripts like a setup.py I wouldn't worry too much about closing files later than expected.
On 25Apr2013 06:49, anatoly techtonik <tech...@gmail.com> wrote:
| On Wed, Apr 24, 2013 at 2:50 PM, Joao S. O. Bueno <jsb...@python.org.br>wrote:
| > On 24 April 2013 05:59, anatoly techtonik <tech...@gmail.com> wrote:
| > > PySide Qt binding have an interesting property - when you create widgets,
| > > you need to assign them to variables. When such variable is lost, object
| > is
| > > immediately destroyed.
| >
| > I truly hope it is not quite as you describe - otherwisew pySie would
| > be completly unusable.
| > What if one adds created objects to a list, instead of assigning them
| > to a variable?
|
| As long as the list references the widget, the widget won't be destroyed.
| "assign to variable" is not a correct term - I guess "reference keeping" is
| better.
Then aren't you just talking about the __del__ method?
The CPython doco says when the reference count goes to zero. (Snippet
below.) So in your example, also immediately.
Garbage collection can find find detached objects whose count hasn't
gone to zero, but I think your example would fit the refs-gone-to-zero,
and anyway I think that was your criterion for having this work in
the first place (automatically).
So I'm not sure how __del__ is particularly less predictable than
your "implicit" scenario.
Then at 25Apr2013 16:17, Steven D'Aprano <st...@pearwood.info> wrote:
| Citation please. Where is this documented?
Well, the 3.2.3 doco on __del__ says:
Called when the instance is about to be destroyed. [...] It is
not guaranteed that __del__() methods are called for objects that
still exist when the interpreter exits. [...]
del x doesn’t directly call x.__del__() — the former decrements
the reference count for x by one, and the latter is only called
when x‘s reference count reaches zero. [ <-- Obviously only valid
for ref counting Python implementations. - Cameron ] Some common
situations that may prevent the reference count of an object from
going to zero include: [...]
The 2.7 doco is very similar.
So, yes, when references go to zero. But as you say later, that may
never happen. The GC _may_ find isolated circles and delete then,
thus at GC time in anatoly's nomenclature.
Reference counting makes __del__ fairly predictable if you have
tight control over the references to an object. Not always the case
of course. And other Pythons don't necessarily do reference counting
unless I misremember.
| Or, and for the record, the reason that with statements work so
| well is because they are guaranteed to be deterministic. You cannot
| leave the with block without the __exit__ method being called. It
| doesn't matter whether you have one reference to the context manager
| object or ten references, the __exit__ method is still called, and
| the object still exists.
This is why I'm for with statements also.
| That is *very* different from a destructor method.
[... snip other stuff I agree with...; I fact I agree with everything
you say but anatoly is not totally off the mark with "GC time". ]
Yep.
--
Cameron Simpson <c...@zip.com.au>
I am now convinced that theoretical physics is actual philosophy.
- Max Born
On 25/04/13 14:47, anatoly techtonik wrote:
On Thu, Apr 25, 2013 at 7:23 AM, Cameron Simpson <c...@zip.com.au> wrote:
Citation please. Where is this documented?Then aren't you just talking about the __del__ method?
No. The __del__ method is only called during garbage collection phase which
may be delayed. In PySide the QObject is deleted immediately.
This thread on the PySide mailing list suggests that you are mistaken, PySide does not have superpowers over and above Python's garbage collector, and is subject to the exact same non-deterministic destructors as any other Python object. Whether you call that destructor __del__ or __exit__ makes no difference.
http://www.mail-archive.com/pys...@lists.openbossa.org/msg01029.html
Or, and for the record, the reason that with statements work so well is because they are guaranteed to be deterministic. You cannot leave the with block without the __exit__ method being called. It doesn't matter whether you have one reference to the context manager object or ten references, the __exit__ method is still called, and the object still exists. That is *very* different from a destructor method.
On the other hand, objects being freed is not deterministic. They'll be freed when there are no longer any references to it, which may be Never.
Reference counting GCs are deterministic, but cannot deal with circular references. Other GCs can deal with circular references, but are non-deterministic. Even the Java GC doesn't guarantee that the finalize() method will always be called.
What proposal? What you appear to propose is either that implementations must use a reference counting collector (more or less ensuring that the file will be closed after the call to read in your example), or that the exit part of the context protocol is run whenever an object is going out of scope.
On 25 Apr, 2013, at 6:00, anatoly techtonik <tech...@gmail.com> wrote:
> On Wed, Apr 24, 2013 at 12:23 PM, Ronald Oussoren <ronaldo...@mac.com> wrote:
>
>
>
>
> On 24 Apr, 2013, at 10:59, anatoly techtonik <tech...@gmail.com> wrote:
>
> > Long time no see, all. :P
> >
> > PySide Qt binding have an interesting property - when you create widgets, you need to assign them to variables. When such variable is lost, object is immediately destroyed.
> >
> > I often use this one-shot code in setup.py:
> > ...
> > long_description = open('README.txt').read(),
> > ....
> >
> > Which probably leaves the README.txt file open until the setup.py exits. So, the idea is to close the file as soon as the variable is lost.
>
> The file is automaticly closed as soon as the file object is garbage collected. In your example CPython would currently collect at the end of the read call (unles there is an exception) because of the reference counting garbage collector, but other implementations have other garbage collectors and can collect the file object (much) later.
>
> Right. Automatic context manager proposal brings this mechanism from garbage collection implementation level to language definition level.
Automaticly calling __exit__ when an object goes out of scope won't work either, it would break passing arguments to functions.
The proposal is fully illustrated by the user story above - immediately close file after it is read operation is complete. The proposed implementation is automatic context manager -- optional, Python level mechanism to run exit part of the context protocol when object loses all references. GC is out of scope here.
Automaticly calling __exit__ when an object goes out of scope won't work either, it would break passing arguments to functions.
Why? Can you provide an example?
On 04/26/2013 06:02 AM, anatoly techtonik wrote:
On Thu, Apr 25, 2013 at 9:17 AM, Steven D'Aprano <st...@pearwood.info <mailto:st...@pearwood.info>> wrote:
On 25/04/13 14:47, anatoly techtonik wrote:
On Thu, Apr 25, 2013 at 7:23 AM, Cameron Simpson <c...@zip.com.au <mailto:c...@zip.com.au>> wrote:Here:Â http://qt-project.org/wiki/PySide_Pitfalls
Then aren't you just talking about the __del__ method?
No. The __del__ method is only called during garbage collection phase which
may be delayed. In PySide the QObject is deleted immediately.
Citation please. Where is this documented?
* Pass a parent QObject to the object’s constructor, so it gets owned by the parent
"""
If a QObject falls out of scope in Python, it will get deleted. You have to take care of keeping a reference to the object:
* Store it as an attribute of an object you keep around, e.g. self.window = QMainWindow()
"""
This thread on the PySide mailing list suggests that you are mistaken, PySide does not have superpowers over and
above Python's garbage collector, and is subject to the exact same non-deterministic destructors as any other Python
object. Whether you call that destructor __del__ or __exit__ makes no difference.
You'll notice it doesn't say "gets /immediately/ deleted" -- because it doesn't. It gets deleted when it gets garbage collected.
"""* Pass a parent QObject to the object’s constructor, so it gets owned by the parent
If a QObject falls out of scope in Python, it will get deleted. You have to take care of keeping a reference to the object:
* Store it as an attribute of an object you keep around, e.g. self.window = QMainWindow()
"""
This thread on the PySide mailing list suggests that you are mistaken, PySide does not have superpowers over and
above Python's garbage collector, and is subject to the exact same non-deterministic destructors as any other Python
object. Whether you call that destructor __del__ or __exit__ makes no difference.
You'll notice it doesn't say "gets /immediately/ deleted" -- because it doesn't. It gets deleted when it gets garbage collected.
Are you sure about that? The example on the PySide wiki is pretty reproducible. With current garbage collector lazyness it should be at least in some cases non-reliable.
On Fri, Apr 26, 2013 at 9:54 PM, <rand...@fastmail.us> wrote:interesting idea. I see nothing bad with proposed construction.
> What about a with expression?
>
> boolean = x.use() with x as open(resource)
Any objections? I've miss something?
with(open(resource)).use()
result = [x.foo(), x.bar()] with open(resource) as x
@contextmanagerdef assign(x):yield xresult = (-b + sqrt(b*b - 4 * a * c)) / (2 * a) with assign(3) as a with assign(4) as b with assign(5) as c
I'd note that there's no reason you couldn't use the so-called "automatic context manager" already, it's just a matter of writing your own function rather than the built-in 'open()'. So, e.g. with a few lines of definition, you might use:
boolean = SafeOpen(resource).use()
You might get really perverse with stack inspection and whatnot. But I was thinking more of just a proxy method that introduced the safety.
class SafeOpen(object):
def __init__(self, resource):
self.resource = resource
def __getattr__(self, name):
def f(*args, **kws):
with open(self.resource) as x:
y = getattr(x, name)(*args, **kws)
return y
return f
> Wouldn't that close the resource before the use function is actually called? As I read it, it opens, calls getattr(x, 'use'), closes x, then calls x.use().
Nope. The call is inside the context manager. Whatever is returned is stored in 'y' before the resource is closed, and that value of y is returned by the proxy function f.
On Fri, Apr 26, 2013 at 12:30 PM, Andrew Svetlov <andrew....@gmail.com> wrote:
On Fri, Apr 26, 2013 at 9:54 PM, <rand...@fastmail.us> wrote:interesting idea. I see nothing bad with proposed construction.
> What about a with expression?
>
> boolean = x.use() with x as open(resource)
Any objections? I've miss something?
The most obvious thing as that 'as' is backwards from the with statement. Also this requires you to come up with a name which you have to repeat while
with(open(resource)).use()
doesn't. On the other hand, it allows you to do:
result = [x.foo(), x.bar()] with open(resource) as x
which opens the way to freewheeling inline assignment:
@contextmanagerdef assign(x):yield x
result = (-b + sqrt(b*b - 4 * a * c)) / (2 * a) with assign(3) as a with assign(4) as b with assign(5) as c
I don't think that's a good thing.