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
ElementTree.iterparse "leaks" file descriptor when not exhausted #101438
The PR #31696 attempts to fix the "leak" of file descriptors when the iterator is not exhausted. That PR fixes the warning, but not the underlying issue that the files aren't closed until the next tracing garbage collection cycle.
Note that there isn't truly a leak of file descriptors. The file descriptors are eventually closed when the file object is finalized (at cyclic garbage collection). The point of the ResourceWarning (in my understanding) is that waiting until the next garbage collection cycle means that you may temporarily have a lot of unwanted open file descriptors, which could exhaust the global limit or prevent successful writes to those files on Windows.
# run with ulimit -Sn 1000importxml.etree.ElementTreeasETimporttempfileimportgcgc.disable()
defrun():
withtempfile.NamedTemporaryFile("w") asf:
f.write("<document />junk")
foriinrange(10000):
it=ET.iterparse(f.name)
delitrun()
On my system, after lowering the file descriptor limit to 1000 (via ulimit -Sn 1000) I get:
OSError: [Errno 24] Too many open files: '/tmp/tmpwwmd9gp6'
@rhettinger everything is cleaned up properly once the garbage collector runs. So adding a gc.collect() after the del it would collect the generator and close the file descriptor.
Activity
ericvsmith commentedon Jan 30, 2023
I think this would require something like PEP 533 “Deterministic cleanup for iterators“ to solve.
colesbury commentedon Jan 30, 2023
In this case, I think you can fix it just by avoiding reference cycles that involve the generator. Below is an example refactoring of
iterparse.This avoids two reference cycles that captured the generator created by
iterator(source):iterator(source)to the instance instead of a class attribute_rootup so thatiterator(source)doesn't refer to the instanceit.I'm not sure about a few things including:
it.rootimportant? It's not documented. Is it only for testing?EDIT: the problem is not capturing of the file descriptor, but the generator
iterator(source).rhettinger commentedon Jan 30, 2023
@colesbury Doe the issue persist if you add
gc.collect()after thedel it?colesbury commentedon Jan 30, 2023
@rhettinger everything is cleaned up properly once the garbage collector runs. So adding a
gc.collect()after thedel itwould collect the generator and close the file descriptor.pythongh-101438: possible fix for ElementTree.iterparse leak
pythongh-101438: Avoid reference cycle in ElementTree.iterparse.
gh-101438: Avoid reference cycle in ElementTree.iterparse. (GH-114269)
pythongh-101438: Avoid reference cycle in ElementTree.iterparse. (pyt…
pythongh-101438: Avoid reference cycle in ElementTree.iterparse. (pyt…
[3.12] gh-101438: Avoid reference cycle in ElementTree.iterparse. (GH…
[3.11] gh-101438: Avoid reference cycle in ElementTree.iterparse. (GH…
pythongh-101438: Avoid reference cycle in ElementTree.iterparse. (pyt…
pythongh-101438: Avoid reference cycle in ElementTree.iterparse. (pyt…