sqlalchemy/alembic · error · ImportError
Can't find Python file %s
Error message
Can't find Python file %s
What it means
Raised as ImportError in load_python_file (pyfiles.py:118) when the requested .py file does not exist on disk AND no compiled .pyc/.pyo fallback could be located via pyc_file_from_path. Alembic tries the .py path first, then falls back to bytecode; only if both fail does it raise, meaning the module file is genuinely missing.
Source
Thrown at alembic/util/pyfiles.py:118
def load_python_file(
dir_: str | os.PathLike[str], filename: str | os.PathLike[str]
) -> ModuleType:
"""Load a file from the given path as a Python module."""
dir_ = pathlib.Path(dir_)
filename_as_path = pathlib.Path(filename)
filename = filename_as_path.name
module_id = re.sub(r"\W", "_", filename)
path = dir_ / filename
ext = path.suffix
if ext == ".py":
if path.exists():
module = load_module_py(module_id, path)
else:
pyc_path = pyc_file_from_path(path)
if pyc_path is None:
raise ImportError("Can't find Python file %s" % path)
else:
module = load_module_py(module_id, pyc_path)
elif ext in (".pyc", ".pyo"):
module = load_module_py(module_id, path)
else:
assert False
return module
def load_module_py(module_id: str, path: str | os.PathLike[str]) -> ModuleType:
spec = importlib.util.spec_from_file_location(module_id, path)
assert spec
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # type: ignore
return module
def _preserving_path_as_str(path: str | os.PathLike[str]) -> str:View on GitHub (pinned to 44fb345033)
Solutions
- Verify the file path exists: check `dir_ / filename` resolves to a real .py file.
- Correct the script_location / -x argument in alembic.ini or the CLI to point at the actual env.py directory.
- If running sourceless, ensure a valid .pyc is present at the expected cache location or alongside the source path.
- Re-run `alembic init` if the migrations tree was deleted.
Example fix
# before: alembic.ini points at a moved env script_location = migrations # env actually at migrations/env.py but file was deleted/renamed # after: correct path script_location = alembic # with alembic/env.py present
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
import importlib.util
def python_file_loadable(dir_, filename) -> bool:
p = Path(dir_) / filename
if p.exists() and p.suffix == '.py':
return True
# check for .pyc fallback
spec = importlib.util.spec_from_file_location('m', p)
return spec is not None and Path(importlib.util.cache_from_source(p.as_posix())).exists()
if not python_file_loadable(dir_, 'env.py'):
raise SystemExit('env.py not found and no .pyc fallback') Try / catch
from alembic.util.pyfiles import load_python_file
try:
module = load_python_file(dir_, 'env.py')
except ImportError as e:
print(f'{e}. Check script_location in alembic.ini and that the file exists.')
raise Prevention
- Verify script_location and env path in alembic.ini after any move/rename.
- Include the migrations directory in Docker images and CI checkouts.
- Run `alembic current` as a smoke test to catch missing-file errors early.
When it happens
Trigger: Pointing alembic at a config/env.py path that does not exist; load_python_file(dir_, filename) with a typo in the filename; running in an environment where only a partial install exists (py present in source tree but file deleted); a deployment that ships only .pyc but the .pyc is also missing or in a different cache location.
Common situations: Misconfigured sqlalchemy.url or script_location in alembic.ini pointing at a non-existent path; renaming/moving env.py without updating references; fresh checkout missing a generated file; Docker image that excluded the migrations directory.
Related errors
- No context has been configured yet.
- Connection, url, or dialect_name is required.
- A plugin named {name} is already registered
- Invalid plugin expression {name!r}
- Cycle is detected in revisions (%s)
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/f39bc862f9da397e.json.
Report an issue: GitHub.