importlib does unnecessary os.stat calls checking for namespace __init__.py files
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 36k
- PR merge metrics
- PR metrics pending
Description
Overall, importlib is very good at caching and not searching over and over again. For instance, if you add new sys.path it won't traverse previous paths again. Except for one thing: it will check for the existence of __init__.py files on all namespace paths again.
It may sound minor, but on a project with heavy namespace use and a lot of sys.path it means a lot of extra FS access on each sys.path change. On windows it is especially slow.
Repro script:
import tempfile
import sys
import importlib
import os
from pathlib import Path
MODULES = [
"namespace_1/foo.py",
"namespace_1/bar.py",
"namespace_1/xyz.py",
"namespace_2/foo.py",
"namespace_2/bar.py",
"namespace_2/xyz.py",
]
with tempfile.TemporaryDirectory() as root:
def _create_module(path):
path = Path(root).joinpath(path)
path.parent.mkdir(exist_ok=True)
open(path, "w").close()
for m in MODULES:
_create_module(m)
def my_stat(path):
print(path)
return os.stat(path)
importlib._bootstrap_external._path_stat = my_stat
sys.path.append(root)
for i, m in enumerate(MODULES):
# Critical line: invalidate sys.path cache
sys.path.append(root + "/{i}")
module_name = m.replace("/", ".").replace(".py", "")
print(f"> importing: {module_name}")
importlib.import_module(module_name)
After each import you will see again and again:
C:\Users\[user]\AppData\Local\Temp\tmpz9rexobt\namespace_2\__init__.cp37-win_amd64.pyd
C:\Users\[user]\AppData\Local\Temp\tmpz9rexobt\namespace_2\__init__.pyd
C:\Users\[user]\AppData\Local\Temp\tmpz9rexobt\namespace_2\__init__.py
C:\Users\[user]\AppData\Local\Temp\tmpz9rexobt\namespace_2\__init__.pyw
C:\Users\[user]\AppData\Local\Temp\tmpz9rexobt\namespace_2\__init__.pyc
Tested on python 3.7, but previously I checked it is the same on the latest one.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the repro script and inspect Python's importlib._bootstrap_external._path_stat entry point and the namespace-package lookup path. Confirm the repeated filesystem checks after each sys.path change, then add focused regression coverage. Done means namespace imports remain correct while avoiding redundant init.py existence checks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100