pythonwindows-subsystem-for-linuxpyproject.tomluv

ModuleNotFoundError when installing my own project


I am working in WSL, with uv. Created a venv (activated). Using Python 3.12.

Then I have a standard pyproject.toml:

[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"

[project]
...

[project.scripts]

run-module= "my_module.main:start"

The project folder structure is as follows:

my_module/
├── pyproject.toml
├── ...
├── my_module/
     ├── __init__.py
     └── main.py
     └── models/
          ├── __init__.py
          └── search.py

Every subsequent folder (like /models) is inside /my_module and with its own __init__.py

Inside main.py, I use absolute imports, like:

from my_module.models.search import SearchWithFilter

Then I install everything with

uv pip install -e .

No error is thrown, and when running a uv pip list, all dependencies, including my own package are listed.

Package            Version    Editable project location
------------------ ---------- ----------------------------
annotated-types    0.7.0
beautifulsoup4     4.12.3
certifi            2024.12.14
charset-normalizer 3.4.1
idna               3.10
pydantic           2.10.4
pydantic-core      2.27.2
requests           2.32.3
soupsieve          2.6
my_module          0.0.1      /home/xxx/projects/my_module
typing-extensions  4.12.2
urllib3            2.3.0

But when trying to run my code:

Traceback (most recent call last):
  File "/home/xxx/projects/my_module/.venv/bin/run-module", line 5, in <module>
    from my_module.main import start
ModuleNotFoundError: No module named 'my_module'

If instead of the installed script I try a direct python3 main.py the same ModuleNotFoundError shows.

I am completely lost at this point. Any idea what can be wrong? By the way I have the very same project template in my work computer and this is working just fine.

Tried reinstalling the whole WSL, reinstalling uv, ... I have also tested a project structure with ./src/my_module with the same result.


Solution

  • You must indicate pyproject.toml where your module namespace (source directory) is. By default, this takes the root directory where the pyproject.toml file resides as the root and expect one .py file there which will be the module (by default hello.py when constructed with uv init) .

    I supposed you have created the project with the equivalent of:

    uv init my_module

    Which leads to the following file tree:

    my_module/
    ├── README.md
    ├── hello.py
    ├── pyproject.toml
    └── uv.lock
    

    I added a start() function to hello.py that just print something. This is only to illustrate what's happening to be close to your pyproject.toml situation.

    Here is the first pyproject.toml

    [build-system]
    requires = ["setuptools >= 61.0"]
    build-backend = "setuptools.build_meta"
    
    [project]
    ...
    
    [project.scripts]
    run-module= "hello:start"
    

    So if I run:

    uv pip install .

    I can also run:

    uv run run-module

    And I got the print from my start function in hello.py which is:

    Start function from my-module!
    

    So now you need to indicate pyproject.toml where your "package" namespace is in your pyproject.toml according to your build system (here setuptools). It will inform where is your project sources are, for you: my_module/

    So now I completely fit with your project folder structure:

    my_module/
    ├── README.md
    ├── my_module
    │   ├── __init__.py
    │   ├── main.py
    │   └── models
    │       └── __init__.py
    ├── pyproject.toml
    └── uv.lock
    

    And added the [tool.setuptools.packages.find] in your pyproject.toml:

    [build-system]
    requires = ["setuptools >= 61.0"]
    build-backend = "setuptools.build_meta"
    
    [project]
    ...
    
    [tool.setuptools.packages.find]
    where = ["./"]
    include = ["my_module"]
    
    [project.scripts]
    run-module= "my_module.main:start"
    

    And this would run as expected:

    uv run run-module

    I hope this helps anyone who struggles with this mostly as it is hard to find the related documentation without the right keywords such as "package namespace".

    With poetry this is slightly different; it uses the package definition in the [project] section. The solution given here fits for your use-case where the build system is setuptools.

    I hope this works on your side after you try, enjoy!

    References: