pythonimportentry-point

Using __main__.py as entry point of Python module


Consider I have a module call app and some user wants to import it on its script caller.py. The user has a local copy of the module app and his file structure is like this

parent_folder
├── caller.py
└── app
    ├── script_1.py
    ├── script_1.py
    └── __main__.py

__main__.py should be the entry point of app with some imports (pointing to script_1 and script_2 modules), classes and functions definitions.

# __main__.py
from app.script_1 import MyClassB
from app.script_2 import MyClassC


class MyClassA:
    def __init__(self):
        print('This instanciate a MyClassA object')

def func_a():
    print('Some Function')

Consider caller.py the user's script that should be able to import app and use its classes and functions.

# caller.py
import app
app.func_a()
obj_a = app.MyClassA()

Running python caller.py on CMD (Windows 10 with Python 3.8.10) I get the error

Traceback (most recent call last):
  File "caller.py", line 2, in <module>
    app.func_a()
AttributeError: module 'app' has no attribute 'func_a'

I know that a modified version of caller.py will work

# caller.py
import app.__main__ as app
app.func_a()
obj_a = app.MyClassA()

With the desired output

Some Function
This instanciate a MyClassA object

However, import app.__main__ as app is far from ideal (not what is usually done when importing modules).

What is missing for me to use __main__.py as entry point of a module when importing from directory?


Solution

  • A package's __main__.py is what gets run if you try to execute the package with python -m. You're not running python -m app. You're running python caller.py. Your __main__.py never runs.

    __init__.py is what gets run to initialize a package. You need an __init__.py, not a __main__.py.