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

  1. Verify the file path exists: check `dir_ / filename` resolves to a real .py file.
  2. Correct the script_location / -x argument in alembic.ini or the CLI to point at the actual env.py directory.
  3. If running sourceless, ensure a valid .pyc is present at the expected cache location or alongside the source path.
  4. 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

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


AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04). Data as JSON: /data/errors/f39bc862f9da397e.json. Report an issue: GitHub.