Replying to Stefan's XXX comments!

3 views
Skip to first unread message

snim2

unread,
Jul 27, 2010, 7:06:48 PM7/27/10
to python-csp
OK, just a few things:


In csp/os_process.py :

__getitem__ in Par can be used like this:

p = Par(p1, p2, ...)

print p[0]
# prints p1

it has to catch IndexError in case client code asks for an index >=
the length of Par.procs.

Can gc ever be None? Probably not, but that bugfix shouldn't work
either. If an object has a __del__ method then the GC does not
collect the object explicitly but calls __del__ instead. We're using
__del__ to call gc.collect() which is very odd, but the code in tests/
winder_bug will produce literally trillions of objects on the heap if
we don't include this bugfix. It's very paradoxical so I was being
unnecessarily cautious.

I don't think Par.start() should return a value, so I removed the
return statement.

In Alt._preselect() there is no particular semantics of returning
None, but the result of any Alt.select() should be similar to
Channel.read(). Channel.read() must always return /some/ object, hence
we choose to return None from an Alt if no other value can be
returned.

I'll look at the bug that's noted in tests/test_builtins.py but I'm
not sure what the comment about Python 2.7 means.

In csp/builtins.py most things fixed, but I don't understand the
comment about LShift / RShift?

Thanks,

Sarah

Stefan Schwarzer

unread,
Jul 28, 2010, 5:00:15 AM7/28/10
to pytho...@googlegroups.com
Hi Sarah,

On 2010-07-28 01:06, snim2 wrote:
> In csp/os_process.py :
>
> __getitem__ in Par can be used like this:
>
> p = Par(p1, p2, ...)
>
> print p[0]
> # prints p1
>
> it has to catch IndexError in case client code asks for an index >=
> the length of Par.procs.

What the comment was aiming at was: Why do we catch an
IndexError and then raise exactly the same exception class? :-)

Maybe we should raise a more domain-specific exception
instead of a low-level IndexError? If not, just omit the
try/except and write a short comment that the exception can
happen and what it means.

> Can gc ever be None? Probably not, but that bugfix shouldn't work
> either. If an object has a __del__ method then the GC does not
> collect the object explicitly but calls __del__ instead. We're using
> __del__ to call gc.collect() which is very odd, but the code in tests/
> winder_bug will produce literally trillions of objects on the heap if
> we don't include this bugfix. It's very paradoxical so I was being
> unnecessarily cautious.

Do I understand correctly that the bug seems only to be
"fixed" if the `if` statement (not only the `gc.collect`
call) is present?

What's the easiest way to reproduce the bug?

If the objects aren't collected, this usually is due to some
cyclic references where several objects in the cycle have a
__del__ method and the garbage collector doesn't know which
to call first. This is described at
http://docs.python.org/library/gc.html#gc.garbage .

The functions in the `gc` module might help to find the
objects which are are part of such cycles.

> In Alt._preselect() there is no particular semantics of returning
> None, but the result of any Alt.select() should be similar to
> Channel.read(). Channel.read() must always return /some/ object, hence
> we choose to return None from an Alt if no other value can be
> returned.

I guess this _is_ the description of the semantics I asked
for. :) This should be documented IMHO.

> I'll look at the bug that's noted in tests/test_builtins.py but I'm
> not sure what the comment about Python 2.7 means.

The unittest module in Python 2.7 already has a method
`assertListEqual`, see
http://docs.python.org/library/unittest.html#unittest.TestCase.assertListEqual .

> In csp/builtins.py most things fixed, but I don't understand the
> comment about LShift / RShift?

`operator.lshift` returns the first value shifted n times
left, where n is the second value in the call. Even though
each shift means a multiplication by 2 (or division in case
of a right shift), the shift operations are mostly bitwise
operations. Also, they're not defined on float values which
is another indication that they're not intended as numerical
operations.

Sorry, I just see I wrote "logical" in the comment instead
of "bitwise". I moved the lines for LShift and RShift to the
bitwise operations now.

Stefan

snim2

unread,
Jul 28, 2010, 9:03:15 AM7/28/10
to python-csp

On Jul 28, 10:00 am, Stefan Schwarzer <sschwar...@sschwarzer.net>
wrote:
> Hi Sarah,
>
> On 2010-07-28 01:06, snim2 wrote:
>
> > In csp/os_process.py :
>
> > __getitem__ in Par can be used like this:
>
> > p = Par(p1, p2, ...)
>
> > print p[0]
> > # prints p1
>
> > it has to catch IndexError in case client code asks for an index >=
> > the length of Par.procs.
>
> What the comment was aiming at was: Why do we catch an
> IndexError and then raise exactly the same exception class? :-)

Oh heck, yes that should be removed.

> Maybe we should raise a more domain-specific exception
> instead of a low-level IndexError? If not, just omit the
> try/except and write a short comment that the exception can
> happen and what it means.

Yes, I think IndexError is probably the right exception for an index
error :) Will fix.

> > Can gc ever be None? Probably not, but that bugfix shouldn't work
> > either. If an object has a  __del__ method then the GC does not
> > collect the object explicitly but calls __del__ instead. We're using
> > __del__ to call gc.collect() which is very odd, but the code in tests/
> > winder_bug will produce literally trillions of objects on the heap if
> > we don't include this bugfix. It's very paradoxical so I was being
> > unnecessarily cautious.
>
> Do I understand correctly that the bug seems only to be
> "fixed" if the `if` statement (not only the `gc.collect`
> call) is present?
>
> What's the easiest way to reproduce the bug?

Comment out the __del__ method and run all the programs in tests/
winder_bug. The nested versions of Russel's pi by quadrature should
trigger the bug. In those programs gc.set_debug() is turned on which
will tell you how many objects are on the heap.

> If the objects aren't collected, this usually is due to some
> cyclic references where several objects in the cycle have a
> __del__ method and the garbage collector doesn't know which
> to call first. This is described athttp://docs.python.org/library/gc.html#gc.garbage.
>
> The functions in the `gc` module might help to find the
> objects which are are part of such cycles.

Well, I couldn't figure out how, but just calling gc.collect() does
collect them, so I can't quite understand why collection doesn't run
"often enough". *shrug*

> > In Alt._preselect() there is no particular semantics of returning
> > None, but the result of any Alt.select() should be similar to
> > Channel.read(). Channel.read() must always return /some/ object, hence
> > we choose to return None from an Alt if no other value can be
> > returned.
>
> I guess this _is_ the description of the semantics I asked
> for. :) This should be documented IMHO.

OK, will do.

> > I'll look at the bug that's noted in tests/test_builtins.py but I'm
> > not sure what the comment about Python 2.7 means.
>
> The unittest module in Python 2.7 already has a method
> `assertListEqual`, seehttp://docs.python.org/library/unittest.html#unittest.TestCase.assert....

OK, fine. So if we're not using csp/unittest.py I'll remove it from
the repo.

> > In csp/builtins.py most things fixed, but I don't understand the
> > comment about LShift / RShift?
>
> `operator.lshift` returns the first value shifted n times
> left, where n is the second value in the call. Even though
> each shift means a multiplication by 2 (or division in case
> of a right shift), the shift operations are mostly bitwise
> operations. Also, they're not defined on float values which
> is another indication that they're not intended as numerical
> operations.
>
> Sorry, I just see I wrote "logical" in the comment instead
> of "bitwise". I moved the lines for LShift and RShift to the
> bitwise operations now.
>

OK, great!

Thanks,

Sarah
Reply all
Reply to author
Forward
0 new messages