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]

Reply via email to