"Can't copy" warning with nested loops

3 views
Skip to first unread message

Richard Thomas

unread,
Jul 24, 2009, 9:31:22 AM7/24/09
to Reinteract
I couldn't see any previous mention of this in TRAC or in the group,
so thought it worth mentioning. If you try to modify an array within a
nested loop...

sum_b = ([10, 20, 30])
for a in range(3):
for b in range(4):
sum_b[a] += b

...it gives an (apparently benign) warning:

'sum_b[...]' apparently modified, but can't copy it

No such warning is given when run directly from the command line with
python. As a very new user of python, let me know if I doing something
wrong here. Otherwise, would it be helpful if I entered a TRAC defect
report for it.

Richard
(Python 2.5.2, Reinteract 0.5.0)

Robert Schroll

unread,
Jul 25, 2009, 8:36:34 PM7/25/09
to reint...@googlegroups.com

This is indeed a problem with Reinteract. The problem lies in the part
of the code that attempts to track and copy objects that are modified,
so that a previous state can be restored when a statement it edited and
re-executed. I don't know what Reinteract is trying and failing to
copy. It's not sum_b itself, since that is properly restored before the
for loop is re-executed.

A Trac ticket is probably a good idea. Hopefully this will be a rather
straight-forward issue for someone who actually knows the code.

Robert

Owen Taylor

unread,
Jul 25, 2009, 10:37:17 PM7/25/09
to reint...@googlegroups.com

Sadly, not completely straightforward:

c = [[1, 2], [3,4]]
c[1] += [2]

Then before the line c[1] += [2], we need to make a "backup" copy of c
so we can rewind execution to that point.

Reinteract normally does a backup copy as a shallow copy. But a
shallow copy of c isn't good enough because the line c[1] += [2]
actually goes ahead and "mutates" not just C, but the [3,4] array that
it points. To so, reinteract does a shallow copy of C, and then it
descends one level deeper and makes a shallow copy of [3,4].

Richards example:

for a in range(3):
for b in range(4):
sum_b[a] += b

Is a lot like the c[1] += [2], except that the elements we are doing a
"deep mutation" on are determined at runtime. What reinteract does is
(effectively) rewrite the statement to be:

sum_b = copy.copy(sum_b)
sum_b[a] = copy.copy(sum_b[a])


for a in range(3):
for b in range(4):
sum_b[a] += b

But at the second line, a is undefined, so it fails. What might be
possible to do is to actually insert the "backup" statements right
into place immediately before the modifying statement, so we have
instead:

sum_b = copy.copy(sum_b)


for a in range(3):
for b in range(4):

sum_b[a] = copy.copy(sum_b[a])
sum_b[a] += b

Which should work, though a bit slowly. There might be some other
pitfalls with that that I'm not thinking of right at the moment.

A ticket would definitely be appreciated so that I remember to look at
this when I have some time to get back to reinteract.

- Owen

Reply all
Reply to author
Forward
0 new messages