Skip to content
39 changes: 14 additions & 25 deletions Lib/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,9 @@ def walk(top, topdown=True, onerror=None, followlinks=False):

dirs = []
nondirs = []
walk_dirs = []
if not topdown:
# Yield after sub-directory traversal if going bottom up
stack.append((top, dirs, nondirs))

# We may not have read permission for top, in which case we can't
# get a list of the files the directory contains.
Expand All @@ -375,41 +377,34 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
try:
with scandir(top) as entries:
for entry in entries:
is_dir = False
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()
if is_dir and not topdown:
# Exclude symlink if followlinks is False
if followlinks or not entry.is_symlink():
# Traverse into sub-directory
stack.append(entry.path)
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
pass

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)
if not topdown:
# Undo additions to stack.
while not isinstance(stack.pop(), tuple):
pass
continue

if topdown:
Expand All @@ -424,12 +419,6 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
# 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))
# Traverse into sub-directories
for new_path in reversed(walk_dirs):
stack.append(new_path)

__all__.append("walk")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Slightly speed up :func:`os.walk` by simplifying exception handling.