]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-119169: Slightly speed up `os.walk(topdown=True)` (GH-121431)
authorBarney Gale <barney.gale@gmail.com>
Wed, 3 Sep 2025 11:57:01 +0000 (12:57 +0100)
committerGitHub <noreply@github.com>
Wed, 3 Sep 2025 11:57:01 +0000 (13:57 +0200)
GH-119186: Slightly speed up `os.walk(topdown=True)`

When `os.walk()` traverses into subdirectories in top-down mode, call
`os.path.join()` once to add a trailing slash, and use string concatenation
thereafter to generate child paths.

Lib/os.py
Misc/NEWS.d/next/Library/2024-07-06-14-32-30.gh-issue-119186.E5B1HQ.rst [new file with mode: 0644]

index 12926c832f5ba5c5cc6bfd5e5905eef654835a88..710d6f8cfcdf74fe326723d8b8658a8202198070 100644 (file)
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -417,14 +417,16 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
             # Yield before sub-directory traversal if going top down
             yield top, dirs, nondirs
             # Traverse into sub-directories
-            for dirname in reversed(dirs):
-                new_path = join(top, dirname)
-                # bpo-23605: os.path.islink() is used instead of caching
-                # entry.is_symlink() result during the loop on os.scandir() because
-                # the caller can replace the directory entry during the "yield"
-                # above.
-                if followlinks or not islink(new_path):
-                    stack.append(new_path)
+            if dirs:
+                prefix = join(top, top[:0])  # Add trailing slash
+                for dirname in reversed(dirs):
+                    new_path = prefix + dirname
+                    # bpo-23605: os.path.islink() is used instead of caching
+                    # entry.is_symlink() result during the loop on os.scandir() because
+                    # the caller can replace the directory entry during the "yield"
+                    # above.
+                    if followlinks or not islink(new_path):
+                        stack.append(new_path)
         else:
             # Yield after sub-directory traversal if going bottom up
             stack.append((top, dirs, nondirs))
diff --git a/Misc/NEWS.d/next/Library/2024-07-06-14-32-30.gh-issue-119186.E5B1HQ.rst b/Misc/NEWS.d/next/Library/2024-07-06-14-32-30.gh-issue-119186.E5B1HQ.rst
new file mode 100644 (file)
index 0000000..fbb4f58
--- /dev/null
@@ -0,0 +1,2 @@
+Slightly speed up :func:`os.walk` by calling :func:`os.path.join` less
+often.