1

I am trying to build a python package. After reading documentation and other tutorials about modules and packages, I am still a bit confused about how limit the modules/packages exposed on the public interface of the root package (meaning the stuff that the user can import and use with the package).

For example, I have a sample project structured like the following:

├── README.md
├── main_package
│   ├── __init__.py
│   ├── config.py
│   ├── main.py
│   ├── sub_package_1
│   │   ├── __init__.py
│   │   └── sub1.py
│   └── sub_package_2
│       ├── __init__.py
│       └── sub2.py
├── package.json
└── setup.py

main_package/main.py

from .config import Config
from .sub_package_1 import sub1_func
from .sub_package_2 import sub2_func

def main_func():
    print(Config.DUMMY, sub1_func(), sub2_func())

main_package/__init__.py

from .main import main_func

main_package/sub_package_1/sub1.py

def sub1_func():
    return 'sub1_func'

main_package/sub_package_1/__init__.py

from .sub1 import sub1_func

main_package/sub_package_2/sub2.py

def sub2_func():
    return 'sub2_func'

main_package/sub_package_2/__init__.py

from .sub2 import sub2_func

What I would like to know if there is a way to selectively control what will be exported (visible) on the public interface of the main package. Let's say for this example I want to export only main_func from main_package.main and the subpackage sub_package_1 and anything else. Can I do that?

from main_package import main_func  # OK
from main_package import config  # NO!
from main_package.sub_package_1 import sub1_func  # OK
from main_package.sub_package_2 import sub2_func  # NO!

It seems I am unable to do so. Every time I build the package, I can import both the sub packages and also the config.py module which I don't want at all.

revy
  • 3,945
  • 7
  • 40
  • 85
  • 1
    Interesting question, I think I briefly looked at a similar thing for private state variables but I think my conclusion then was that Python has no notion of private members of any sort, even though you can indicate what shouldn't be called with documentation. I think quite a few SO threads see people importing a library's internal helper function, so I think the "dangerous" scenario you're trying to avoid can't be helped much – fibonachoceres Oct 11 '20 at 09:22
  • You can define list/tuple `__all__` only what is listed there can be imported – Sedy Vlk Oct 11 '20 at 18:38
  • 1
    @SedyVlk I am afraid that will only impact what you can import with `from import *` statement: https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python – revy Oct 14 '20 at 09:59
  • There is no privacy in Python. So the answer is you can't. But you can prefix with an underscore every name for internal use. So at least the user knows these were not meant for import. – progmatico Oct 18 '20 at 18:32

0 Answers0