scandir, a better directory iterator
scandir is a Python library that provides a faster directory iterator and a faster `os.walk()` implementation than the standard library's `os.listdir()` and `os.walk()` for older Python versions. It backported the functionality that was later added to Python 3.5 as `os.scandir`. The current version is 1.10.0, with releases occurring infrequently as new Python versions are supported or critical fixes are needed.
Warnings
- breaking Version 1.10.0 removed support for Python 2.6 and Python 3 versions less than 3.4.
- gotcha For Python 3.5 and newer, the functionality of `scandir` (and an optimized `os.walk`) is built into the standard `os` module (`os.scandir`, `os.walk`). It's generally recommended to use the built-in functions in Python 3.5+ for better compatibility and fewer external dependencies, unless specific performance needs dictate the `scandir` library's C extension.
- gotcha The C extension is optional as of v1.8. If the C extension fails to build or is unavailable (e.g., on specific platforms like Jython), a slower pure-Python fallback will be used. This can lead to unexpected performance degradation if the C extension is assumed.
- gotcha The type of `entry.stat().st_Xtime` (e.g., `st_atime`, `st_mtime`) changed from `int` to `float` in version 1.4 to better mimic `os.stat` behavior. Code relying on integer timestamps might need adjustment.
- gotcha Historically, unicode handling on Python 2.x and specific operating systems (Windows, Linux, OpenBSD, Solaris) has had several fixes across versions (v1.2, v1.3, v1.6, v1.10.0). While most common issues are resolved, users on unusual setups or older `scandir` versions might still encounter path encoding issues.
Install
-
pip install scandir
Imports
- scandir
from scandir import scandir
- walk
from scandir import walk
- DirEntry
from scandir import DirEntry
Quickstart
import scandir
import os
def list_dir_contents(path):
try:
print(f"Listing contents of: {path}")
for entry in scandir.scandir(path):
if entry.is_file():
print(f" File: {entry.name}")
elif entry.is_dir():
print(f" Dir: {entry.name}/")
elif entry.is_symlink():
print(f" Symlink: {entry.name} -> {entry.path}")
except FileNotFoundError:
print(f"Error: Directory not found at {path}")
except PermissionError:
print(f"Error: Permission denied for {path}")
# Example usage: list current directory
list_dir_contents('.')
# Example usage: walk a directory tree
print('\nWalking directory tree:')
for root, dirs, files in scandir.walk('.'):
level = root.count(os.sep)
indent = ' ' * 4 * level
print(f'{indent}{os.path.basename(root)}/')
subindent = ' ' * 4 * (level + 1)
for d in dirs:
print(f'{subindent}Dir: {d}/')
for f in files:
print(f'{subindent}File: {f}')