https://github.com/python/cpython/commit/db00fee3a22db1c4b893b432c64a8123d7e92322
commit: db00fee3a22db1c4b893b432c64a8123d7e92322
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
date: 2024-07-08T17:41:01+01:00
summary:
GH-119169: Simplify `os.walk()` exception handling (#121435)
Handle errors from `os.scandir()` and `ScandirIterator` similarly, which
lets us loop over directory entries with `for`.
files:
A Misc/NEWS.d/next/Library/2024-07-06-16-08-39.gh-issue-119169.o0YymL.rst
M Lib/os.py
diff --git a/Lib/os.py b/Lib/os.py
index 4b48afb040e565..aaa758d955fe4c 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -373,61 +373,45 @@ def walk(top, topdown=True, onerror=None,
followlinks=False):
# minor reason when (say) a thousand readable directories are still
# left to visit.
try:
- scandir_it = scandir(top)
+ with scandir(top) as entries:
+ for entry in entries:
+ try:
+ if followlinks is _walk_symlinks_as_files:
+ is_dir = entry.is_dir(follow_symlinks=False) and
not entry.is_junction()
+ else:
+ is_dir = entry.is_dir()
+ except OSError:
+ # If is_dir() raises an OSError, consider the entry
not to
+ # be a directory, same behaviour as os.path.isdir().
+ is_dir = False
+
+ if is_dir:
+ dirs.append(entry.name)
+ else:
+ nondirs.append(entry.name)
+
+ if not topdown and is_dir:
+ # Bottom-up: traverse into sub-directory, but exclude
+ # symlinks to directories if followlinks is False
+ if followlinks:
+ walk_into = True
+ else:
+ try:
+ is_symlink = entry.is_symlink()
+ except OSError:
+ # If is_symlink() raises an OSError, consider
the
+ # entry not to be a symbolic link, same
behaviour
+ # as os.path.islink().
+ is_symlink = False
+ walk_into = not is_symlink
+
+ if walk_into:
+ walk_dirs.append(entry.path)
except OSError as error:
if onerror is not None:
onerror(error)
continue
- cont = False
- with scandir_it:
- while True:
- try:
- try:
- entry = next(scandir_it)
- except StopIteration:
- break
- except OSError as error:
- if onerror is not None:
- onerror(error)
- cont = True
- break
-
- try:
- if followlinks is _walk_symlinks_as_files:
- is_dir = entry.is_dir(follow_symlinks=False) and not
entry.is_junction()
- else:
- is_dir = entry.is_dir()
- except OSError:
- # If is_dir() raises an OSError, consider the entry not to
- # be a directory, same behaviour as os.path.isdir().
- is_dir = False
-
- if is_dir:
- dirs.append(entry.name)
- else:
- nondirs.append(entry.name)
-
- if not topdown and is_dir:
- # Bottom-up: traverse into sub-directory, but exclude
- # symlinks to directories if followlinks is False
- if followlinks:
- walk_into = True
- else:
- try:
- is_symlink = entry.is_symlink()
- except OSError:
- # If is_symlink() raises an OSError, consider the
- # entry not to be a symbolic link, same behaviour
- # as os.path.islink().
- is_symlink = False
- walk_into = not is_symlink
-
- if walk_into:
- walk_dirs.append(entry.path)
- if cont:
- continue
-
if topdown:
# Yield before sub-directory traversal if going top down
yield top, dirs, nondirs
diff --git
a/Misc/NEWS.d/next/Library/2024-07-06-16-08-39.gh-issue-119169.o0YymL.rst
b/Misc/NEWS.d/next/Library/2024-07-06-16-08-39.gh-issue-119169.o0YymL.rst
new file mode 100644
index 00000000000000..5d9b50d452a9cd
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-07-06-16-08-39.gh-issue-119169.o0YymL.rst
@@ -0,0 +1 @@
+Slightly speed up :func:`os.walk` by simplifying exception handling.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]