GH-117727: Speed up pathlib.Path.iterdir() by using os.scandir() (#117728)

Replace use of `os.listdir()` with `os.scandir()`. Forgo setting `_drv`,
`_root` and `_tail_cached`, as these usually aren't needed. Use
`os.DirEntry.path` to set `_str`.
This commit is contained in:
Barney Gale 2024-04-12 23:02:39 +01:00 committed by GitHub
parent 0eb52f5f26
commit 30f0643e36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 20 deletions

View file

@ -584,26 +584,12 @@ class Path(_abc.PathBase, PurePath):
The children are yielded in arbitrary order, and the The children are yielded in arbitrary order, and the
special entries '.' and '..' are not included. special entries '.' and '..' are not included.
""" """
return (self._make_child_relpath(name) for name in os.listdir(self)) root_dir = str(self)
with os.scandir(root_dir) as scandir_it:
paths = [entry.path for entry in scandir_it]
def _make_child_relpath(self, name): if root_dir == '.':
if not name: paths = map(self._remove_leading_dot, paths)
return self return map(self._from_parsed_string, paths)
path_str = str(self)
tail = self._tail
if tail:
path_str = f'{path_str}{self.parser.sep}{name}'
elif path_str != '.':
path_str = f'{path_str}{name}'
else:
path_str = name
path = self.with_segments(path_str)
path._str = path_str
path._drv = self.drive
path._root = self.root
path._tail_cached = tail + [name]
return path
def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=False): def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=False):
"""Iterate over this subtree and yield all existing files (of any """Iterate over this subtree and yield all existing files (of any

View file

@ -0,0 +1,2 @@
Speed up :meth:`pathlib.Path.iterdir` by using :func:`os.scandir`
internally.