How to package multiple single modules as sub-package with python setuptools

Viewed 38

My Directory structure looks like follows.

pkg-folder
├── LICENSE
├── pkg-name
│   ├── __init__.py
│   ├── module1
│   │   ├── module1.py
│   │   ├── __init__.py
│   │   └── resourceFile.json
│   └── module2
│       ├── __init__.py
│       └── module2.py
├── README.md
├── setup.py
├── MANIFEST.ini
└── setup.cfg

After building and installing the package I have to import as follows.

from pkg-name.module1.module1 import func1

How can I import directly like follows when i know module1.py will be a single file in the sub-package ?

from pkg-name.module1 import func1

My __init__.py's are blank.

1 Answers

You've partially answered your own question:

My __init__.py's are blank.

When importing a package, the interpreter checks for name bindings in the package's __init__.py file. An empty __init__.py file only provides name bindings for submodules within the same directory. For example, if you have a package structure like

pkg_folder
└── pkg_name
    └── __init__.py

and __init__.py contains some definition like x = 2, then with pkg_folder as the current working directory or with the package installed to your Python environment, you can import x using

from pkg_name import x

However, if x is defined in a submodule, things are a little different. Consider the following package structure:

pkg_folder
└── pkg_name
    ├── __init__.py
    └── module1.py

Here, import pkg_name again tells the interpreter to check pkg_name/__init__.py for name bindings. If the definition x = 2 is in module1.py instead of __init__.py, then it is not part of pkg_name's scope; instead, it belongs to pkg_name.module1, so the following would work:

from pkg_name.module1 import x

However, you can explicitly add it to pkg_name by defining a name binding for it in __init__.py with a package relative import. In this case, __init__.py might read:

from .module1 import x

Which, since x is now defined in __init__.py, allows us to reference it under pkg_name as well:

from pkg_name import x

The same logic applies to modules within sub-packages. So for the behavior you're looking for, you'll need to populate your sub-package's __init__.py files with package relative imports from the other modules within the sub-package.

To go from

from pkg_name.module1.module1 import func1

to

from pkg_name.module1 import func1

your pkg_name/module1/__init__.py file might resemble something like the following:

from .module1 import func1

If you had reason to, you could even extend this to propagate func1 up to the parent package.

Related