Skip to content

Commit e7a3937

Browse files
gh-93618: Document the memory usage of the incremental parsers (GH-156763)
It was said that iterparse() can be useful for reading a large document without holding it wholly in memory, but the tree is only built incrementally, it is not freed incrementally. Document how to remove the processed elements, and that a custom target does not build a tree at all.
1 parent 658612a commit e7a3937

1 file changed

Lines changed: 35 additions & 2 deletions

File tree

Doc/library/xml.etree.elementtree.rst

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,37 @@ some storage device. In such cases, blocking reads are unacceptable.
160160
Because it's so flexible, :class:`XMLPullParser` can be inconvenient to use for
161161
simpler use-cases. If you don't mind your application blocking on reading XML
162162
data but would still like to have incremental parsing capabilities, take a look
163-
at :func:`iterparse`. It can be useful when you're reading a large XML document
164-
and don't want to hold it wholly in memory.
163+
at :func:`iterparse`.
164+
165+
Note that both parsers build the tree incrementally: it is not freed
166+
incrementally, so every parsed element is kept until the whole document is
167+
read. To keep the memory usage low, get rid of the data which is not needed
168+
any more.
169+
170+
If the processed elements are large, it is enough to clear them.
171+
This works wherever they are in the tree,
172+
but the emptied elements are left in it::
173+
174+
for event, elem in ET.iterparse(source):
175+
if elem.tag == 'record':
176+
process(elem)
177+
elem.clear()
178+
179+
If an element has a large number of children,
180+
remove the processed children from it::
181+
182+
for event, elem in ET.iterparse(source, events=('start', 'end')):
183+
if event == 'start' and elem.tag == 'parent':
184+
parent = elem
185+
elif event == 'end' and elem.tag == 'child':
186+
process(elem)
187+
parent.remove(elem)
188+
189+
These examples are not universal,
190+
they only give an idea for two common cases.
191+
If you do not need a tree at all,
192+
parse with :class:`XMLParser` and a custom target instead;
193+
it is not built then, and nothing has to be removed.
165194

166195
Where *immediate* feedback through events is wanted, calling method
167196
:meth:`XMLPullParser.flush` can help reduce delay;
@@ -635,6 +664,10 @@ Functions
635664
for applications where blocking reads can't be made. For fully non-blocking
636665
parsing, see :class:`XMLPullParser`.
637666

667+
The tree is only built incrementally, it is not freed incrementally:
668+
every parsed element is kept until the whole document is read.
669+
See :ref:`elementtree-pull-parsing` for how to keep the memory usage low.
670+
638671
.. note::
639672

640673
:func:`iterparse` only guarantees that it has seen the ">" character of a

0 commit comments

Comments
 (0)