Home > Mobile >  Python3: setup.py does not install package or subpackages
Python3: setup.py does not install package or subpackages

Time:06-15

I would like help regarding setuptools and imports. I have been unable to run pip install . and have package importable by any arbitrary python script like this

import package

Here is an example file structure I have tried to play with

.
├── setup.py
└── src
    └── package
        ├── __init__.py
        ├── __main__.py
        ├── package1
        │   ├── __init__.py
        │   └── module1.py
        └── package2
            ├── __init__.py
            └── module2.py

Content of setup.py

import setuptools

setuptools.setup(name="package",
      version="1.0.0",
      python_requires='>=3.8',
      package_dir={"package": "src"},
      packages=['package'])

Content of src/package/__init__.py

from . import package1
from . import package2

Content of src/package/__main__.py

import package2
from package2.module2 import function2
if __name__ == '__main__':
    function2()
    print("Hello from main")

Content of src/package/package1/__init__.py

from . import module1

Content of src/package/package1/module1.py

def function1():
    print("Hello from function1")

Content of src/package/package2/__init__.py

from . import module2

Content of src/package/package2/module2.py

import package1
from package1.module1 import function1
def function2():
    function1()
    print("Hello from function2")

If I run __main__.py with python3 src/package the output is

Hello from function1
Hello from function2
Hello from main

It works as I want it from __main__. Now, I want to install package so I can import with a simple import package. I do this with pip install .

I then create a script in an arbitrary folder with this content

import package

However, I get the error /bin/python3.10 /home/ubuntu/tmp/test.py Traceback (most recent call last): File "/home/ubuntu/tmp/test.py", line 1, in <module> import package ModuleNotFoundError: No module named 'package'

My goal is to be able to run a script like this from anywhere and not have it error.

import package
function2()

Output would be

Hello from function1
Hello from function2

What lines of code must change for package to be importable from any script, and why did it not work with the code and filestructure provided above?

CodePudding user response:

Writing {"package": "src"} means "the src directory is the package", it would work if you had:

└── src
    ├── __init__.py
    ├── __main__.py
    ├── package1
    │   ├── __init__.py
    │   ├── module1.py
    ├── package2
    │   ├── __init__.py
    │   ├── module2.py

But you have package inside src so you need to indicate the root folder for your packages with is the empty string of package_dir, like:

package_dir={"": "src"}

Then it starts to work:

$ python setup.py bdist_wheel && unzip -l dist/package-1.0.0-py3-none-any.whl 
  Length      Date    Time    Name
---------  ---------- -----   ----
       46  2022-06-14 09:11   package/__init__.py
      127  2022-06-14 09:12   package/__main__.py

But you're missing the other package, so you either need to list them all:

packages=["package", "package.package1", "package.package2"]

Or make setuptools work for you:

packages=setuptools.find_packages(where="src")

In both cases your 3 packages are installed:

  Length      Date    Time    Name
---------  ---------- -----   ----
       46  2022-06-14 09:11   package/__init__.py
      127  2022-06-14 09:12   package/__main__.py
       22  2022-06-14 09:12   package/package1/__init__.py
       51  2022-06-14 09:12   package/package1/module1.py
       22  2022-06-14 09:12   package/package2/__init__.py
      122  2022-06-14 09:12   package/package2/module2.py
  • Related