0

Say I have a Python package mymodule based on a Pybind11 extension where the following code works like a charm after running python setup.py install:

from mypackage.subA import foo  # foo is written in C++.
from mypackage.subB import bar  # Same for bar.

I now want to add some pure Python code in one of the submodules, say subA, so that I can also do

from mypackage.subA import pure_python_func

I've made an MCVE of such a project to hopefully make this as clear as possible.

If I add a file mypackage/subA.py in which I write pure_python_func (and add an empty mypackage/__init__.py), I can import the Python part, but the extension module disappears. I.e.

from mypackage.subA import pure_python_func  # Works
from mypackage.subA import foo  # Fails
from mypackage.subB import bar  # Fails

My question is how can I end up with a something that has both extension code and Python code within the same package? Preferably within the same submodules, but at least within the same package. Any help is greatly appreciated!

Bendik
  • 1,097
  • 1
  • 8
  • 27

1 Answers1

2

An easy way to do this is to build your C++ module into a protected module outside of your public module, and import this protected module into your public module.

For example, change mypackage.subA.foo to build to _mypackage._foo. Then the file mypackage/subA/__init__.py would look something like this:

from _mypackage._foo import *
from mypackage.subA._pythonModule import *

# Any other python code could be imported here as well
pseudonym117
  • 799
  • 1
  • 5
  • 22
  • I tried something like this, but the issue was that as soon as I added `mypackage/__init__.py` then I could no longer import from the extension module. I think it shadowed the extension module because they were named the same. I'm thinking this is fixable in `setup.py`, but I can't seem to make it work - do you know how it should look to make your suggestion work? – Bendik Jan 22 '19 at 22:32
  • answer updated. I had done this so long ago that I had forgotten that would happen. – pseudonym117 Jan 22 '19 at 22:38
  • That works! Thought I had tried that before, but turns out I forgot to change the name in the CMakeLists.txt file as well as in setup.py and the Pybind11 code. Thanks a lot! – Bendik Jan 22 '19 at 22:56