I have a project with pybind11 extension modules, structured in a hierarchical way.

While importing, I face the following problem:

1. Test 1

1.1. Package structure

org
├── __init__.py
├── sdk
│   ├── core.cpython-37m-x86_64-linux-gnu.so
│   └── __init__.py
└── sdk.cpython-37m-x86_64-linux-gnu.so

1.2. Import type from module org.sdk:

python -c "from org.sdk import CommonType"
1.2.1. Fails with the error:
ImportError: cannot import name 'CommonType' from 'org.sdk' (python3.7/site-packages/org_sdk-0.0.0-py3.7-linux-x86_64.egg/org/sdk/__init__.py)

1.3. Import type from module org.sdk.core:

python -c "from org.sdk.core import A"
1.3.1. Success

2. Test 2

Removed org/sdk/__init__.py

2.1. Package structure

org
├── __init__.py
├── sdk
│   └── core.cpython-37m-x86_64-linux-gnu.so
└── sdk.cpython-37m-x86_64-linux-gnu.so

2.2. Import type from module org.sdk:

python -c "from org.sdk import CommonType"
2.2.1. Success

2.3. Import type from module org.sdk.core:

python -c "from org.sdk.core import A"
2.3.1. Fails with the error:
ModuleNotFoundError: No module named 'org.sdk.core'; 'org.sdk' is not a package

I'd like to know how can I have a solution where both imports would work?

It seems that the default python loader, prefers the org/sdk/__init__.py to load the org.sdk package, is it possible to add some code in the org/sdk/init.py that would also load the pybind11 extension module org/sdk.cpython-37m-x86_64-linux-gnu.so ?

1 Answers

0
Sergei On

A common practice to mix python and C++ in same package is to name pure-C++ module with leading underscore and import from it in python module.

The layout will look like that:

org
├── __init__.py
└── sdk
    ├── __init__.py # import ._core as core
    └── _core.cpython-37m-x86_64-linux-gnu.so