Skip to content

Commit 37651cf

Browse files
authored
GH-125413: pathlib ABCs: use scandir() to speed up walk() (#126262)
Use the new `PathBase.scandir()` method in `PathBase.walk()`, which greatly reduces the number of `PathBase.stat()` calls needed when walking. There are no user-facing changes, because the pathlib ABCs are still private and `Path.walk()` doesn't use the implementation in its superclass.
1 parent 68a51e0 commit 37651cf

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

Lib/pathlib/_abc.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -693,16 +693,18 @@ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
693693
if not top_down:
694694
paths.append((path, dirnames, filenames))
695695
try:
696-
for child in path.iterdir():
697-
try:
698-
if child.is_dir(follow_symlinks=follow_symlinks):
699-
if not top_down:
700-
paths.append(child)
701-
dirnames.append(child.name)
702-
else:
703-
filenames.append(child.name)
704-
except OSError:
705-
filenames.append(child.name)
696+
with path.scandir() as entries:
697+
for entry in entries:
698+
name = entry.name
699+
try:
700+
if entry.is_dir(follow_symlinks=follow_symlinks):
701+
if not top_down:
702+
paths.append(path.joinpath(name))
703+
dirnames.append(name)
704+
else:
705+
filenames.append(name)
706+
except OSError:
707+
filenames.append(name)
706708
except OSError as error:
707709
if on_error is not None:
708710
on_error(error)

Lib/test/test_pathlib/test_pathlib_abc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,7 +1951,7 @@ def ordered_walk(path):
19511951
if self.can_symlink:
19521952
# Add some symlinks
19531953
source.joinpath('linkC').symlink_to('fileC')
1954-
source.joinpath('linkD').symlink_to('dirD')
1954+
source.joinpath('linkD').symlink_to('dirD', target_is_directory=True)
19551955

19561956
# Perform the copy
19571957
target = base / 'copyC'
@@ -2969,7 +2969,7 @@ def setUpWalk(self):
29692969
f.write(f"I'm {path} and proud of it. Blame test_pathlib.\n")
29702970

29712971
if self.can_symlink:
2972-
self.link_path.symlink_to(t2_path)
2972+
self.link_path.symlink_to(t2_path, target_is_directory=True)
29732973
broken_link_path.symlink_to('broken')
29742974
broken_link2_path.symlink_to(self.cls('tmp3', 'broken'))
29752975
self.sub2_tree = (self.sub2_path, [], ["broken_link", "broken_link2", "link", "tmp3"])

0 commit comments

Comments
 (0)