Skip to content

Commit 67d5d0e

Browse files
committed
Closes #7334: close source files on ElementTree.parse and iterparse (partial backport of issue #10093 from 3.2).
1 parent e96102b commit 67d5d0e

File tree

3 files changed

+45
-22
lines changed

3 files changed

+45
-22
lines changed

Lib/xml/etree/ElementTree.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -642,17 +642,23 @@ def _setroot(self, element):
642642
# @exception ParseError If the parser fails to parse the document.
643643

644644
def parse(self, source, parser=None):
645+
close_source = False
645646
if not hasattr(source, "read"):
646647
source = open(source, "rb")
647-
if not parser:
648-
parser = XMLParser(target=TreeBuilder())
649-
while 1:
650-
data = source.read(65536)
651-
if not data:
652-
break
653-
parser.feed(data)
654-
self._root = parser.close()
655-
return self._root
648+
close_source = True
649+
try:
650+
if not parser:
651+
parser = XMLParser(target=TreeBuilder())
652+
while 1:
653+
data = source.read(65536)
654+
if not data:
655+
break
656+
parser.feed(data)
657+
self._root = parser.close()
658+
return self._root
659+
finally:
660+
if close_source:
661+
source.close()
656662

657663
##
658664
# Creates a tree iterator for the root element. The iterator loops
@@ -1189,16 +1195,19 @@ def parse(source, parser=None):
11891195
# @return A (event, elem) iterator.
11901196

11911197
def iterparse(source, events=None, parser=None):
1198+
close_source = False
11921199
if not hasattr(source, "read"):
11931200
source = open(source, "rb")
1201+
close_source = True
11941202
if not parser:
11951203
parser = XMLParser(target=TreeBuilder())
1196-
return _IterParseIterator(source, events, parser)
1204+
return _IterParseIterator(source, events, parser, close_source)
11971205

11981206
class _IterParseIterator(object):
11991207

1200-
def __init__(self, source, events, parser):
1208+
def __init__(self, source, events, parser, close_source=False):
12011209
self._file = source
1210+
self._close_file = close_source
12021211
self._events = []
12031212
self._index = 0
12041213
self.root = self._root = None
@@ -1249,6 +1258,8 @@ def next(self):
12491258
except IndexError:
12501259
if self._parser is None:
12511260
self.root = self._root
1261+
if self._close_file:
1262+
self._file.close()
12521263
raise StopIteration
12531264
# load event buffer
12541265
del self._events[:]

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ Core and Builtins
7171
Library
7272
-------
7373

74+
- Issue #7334: close source files on ElementTree.parse and iterparse.
75+
7476
- Issue #13232: logging: Improved logging of exceptions in the presence of
7577
multiple encodings.
7678

Modules/_elementtree.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,19 +2915,25 @@ init_elementtree(void)
29152915

29162916
"class ElementTree(ET.ElementTree):\n" /* public */
29172917
" def parse(self, source, parser=None):\n"
2918+
" close_source = False\n"
29182919
" if not hasattr(source, 'read'):\n"
29192920
" source = open(source, 'rb')\n"
2920-
" if parser is not None:\n"
2921-
" while 1:\n"
2922-
" data = source.read(65536)\n"
2923-
" if not data:\n"
2924-
" break\n"
2925-
" parser.feed(data)\n"
2926-
" self._root = parser.close()\n"
2927-
" else:\n"
2928-
" parser = cElementTree.XMLParser()\n"
2929-
" self._root = parser._parse(source)\n"
2930-
" return self._root\n"
2921+
" close_source = False\n"
2922+
" try:\n"
2923+
" if parser is not None:\n"
2924+
" while 1:\n"
2925+
" data = source.read(65536)\n"
2926+
" if not data:\n"
2927+
" break\n"
2928+
" parser.feed(data)\n"
2929+
" self._root = parser.close()\n"
2930+
" else:\n"
2931+
" parser = cElementTree.XMLParser()\n"
2932+
" self._root = parser._parse(source)\n"
2933+
" return self._root\n"
2934+
" finally:\n"
2935+
" if close_source:\n"
2936+
" source.close()\n"
29312937
"cElementTree.ElementTree = ElementTree\n"
29322938

29332939
"def iter(node, tag=None):\n" /* helper */
@@ -2957,8 +2963,10 @@ init_elementtree(void)
29572963
"class iterparse(object):\n"
29582964
" root = None\n"
29592965
" def __init__(self, file, events=None):\n"
2966+
" self._close_file = False\n"
29602967
" if not hasattr(file, 'read'):\n"
29612968
" file = open(file, 'rb')\n"
2969+
" self._close_file = True\n"
29622970
" self._file = file\n"
29632971
" self._events = []\n"
29642972
" self._index = 0\n"
@@ -2973,6 +2981,8 @@ init_elementtree(void)
29732981
" except IndexError:\n"
29742982
" if self._parser is None:\n"
29752983
" self.root = self._root\n"
2984+
" if self._close_file:\n"
2985+
" self._file.close()\n"
29762986
" raise StopIteration\n"
29772987
" # load event buffer\n"
29782988
" del self._events[:]\n"

0 commit comments

Comments
 (0)