You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
use both "for in" and "ElementTree.remove" has a index bug #86058
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2020-10-05.04:22:13.395>created_at=<Date2020-09-30.14:20:25.049>labels= ['type-bug', '3.8', '3.9', '3.10', 'expert-XML', 'invalid', 'docs']
title='use both "for in" and "ElementTree.remove" has a index bug'updated_at=<Date2020-10-05.04:22:13.395>user='https://bugs.python.org/WoodyWoo'
#Just run it in Python v3.8.6 of win7 32bit importxml.etree.ElementTreeasETxmlstr='''<root><a no="1"/><b/><c/></root>'''etroot=ET.fromstring(xmlstr)
forELEMchildinetroot:
ifELEMchild.get("no") =="1" :
etroot.remove(ELEMchild) #so far so goodprint (ELEMchild.tag)
#It should be : "b /n c" or "a /n b /n c",I can live with it both.#But it is : "a /n c".#The index of ELEMchild should not +1 when there was a remove method worked on one of the before ELEMs.#I was forced to use while and if to control the index +1/+0.#BTW,ELEM has no method returning index in siblings, which is buging me too.
changed the title [-]use both "for" and "ElementTree.remove" has a index bug[/-][+]use both "for in" and "ElementTree.remove" has a index bug[/+]on Sep 30, 2020
changed the title [-]use both "for" and "ElementTree.remove" has a index bug[/-][+]use both "for in" and "ElementTree.remove" has a index bug[/+]on Sep 30, 2020
>>> a = [1, 2, 3]
>>> for x in a:
... if x ==1:
... a.remove(x)
... print(x)
...
1
3
Lists are iterated by index. First you get an item at index 0, then at index 1, etc, to the end of the list. Initially the list is [1, 2, 3]. After removing 1 at the first iteration it becomes [2, 3], and at the next iteration you get an item at index 1 which is 3.
I can't say how ElementTree works without more checking, but this solution cannot work in general. Given a pointer to an object that's in a list, how would you get to the next item? Say the parent list-like object has a C array of pointers to the objects it contains, and removing one of the objects re-shuffles that list. How would keeping a pointer to the current object help you?
In any event, I don't think this behavior is going to change.
New changeset 40db798 by scoder in branch 'master': bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464) 40db798
New changeset 6bd058e by Miss Skeleton (bot) in branch '3.8': bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464) 6bd058e
New changeset d571924 by Miss Skeleton (bot) in branch '3.9': bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464) (GH-22554) d571924
Activity
WoodyWoo commentedon Sep 30, 2020
[-]use both "for" and "ElementTree.remove" has a index bug[/-][+]use both "for in" and "ElementTree.remove" has a index bug[/+][-]use both "for" and "ElementTree.remove" has a index bug[/-][+]use both "for in" and "ElementTree.remove" has a index bug[/+]ericvsmith commentedon Sep 30, 2020
I assume that ElementTree doesn't support mutation while iterating.
However, the docs at https://docs.python.org/3/library/xml.etree.elementtree.html#modifying-an-xml-file show removing an item while iterating. It probably only works because the child being removed is the last one.
serhiy-storchaka commentedon Sep 30, 2020
You will get the same behavior for lists:
Lists are iterated by index. First you get an item at index 0, then at index 1, etc, to the end of the list. Initially the list is [1, 2, 3]. After removing 1 at the first iteration it becomes [2, 3], and at the next iteration you get an item at index 1 which is 3.
ericvsmith commentedon Sep 30, 2020
I think the only action here is to improve the documentation. That example is especially problematic.
8 remaining items
WoodyWoo commentedon Oct 1, 2020
@eric.smith @scoder @serhiy.storchaka Thank U all.
I get what to do,and still think the "for in" structure should rebuilding.
All three methods:
WoodyWoo commentedon Oct 1, 2020
Could I say the mutable sequence containing not the object but the pointer like C++.
So they can changed in def functions.
ericvsmith commentedon Oct 1, 2020
I can't say how ElementTree works without more checking, but this solution cannot work in general. Given a pointer to an object that's in a list, how would you get to the next item? Say the parent list-like object has a C array of pointers to the objects it contains, and removing one of the objects re-shuffles that list. How would keeping a pointer to the current object help you?
In any event, I don't think this behavior is going to change.
ned-deily commentedon Oct 4, 2020
New changeset 40db798 by scoder in branch 'master':
bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464)
40db798
miss-islington commentedon Oct 4, 2020
New changeset 6bd058e by Miss Skeleton (bot) in branch '3.8':
bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464)
6bd058e
ned-deily commentedon Oct 4, 2020
New changeset d571924 by Miss Skeleton (bot) in branch '3.9':
bpo-41892: Clarify that an example in the ElementTree docs explicitly avoids modifying an XML tree while iterating over it. (GH-22464) (GH-22554)
d571924
scoder commentedon Oct 5, 2020
Closing since this works as designed.
Users are responsible for avoiding concurrent tree modifications during iteration.