4

In a Python package directory of my own creation, I have an __init__.py file that says:

from _foo import *

In the same directory there is a _foomodule.so which is loaded by the above. The shared library is implemented in C++ (using Boost Python). This lets me say:

import foo
print foo.MyCppClass

This works, but with a quirk: the class is known to Python by the full package path, which makes it print this:

foo._foo.MyCppClass

So while MyCppClass exists as an alias in foo, foo.MyCppClass is not its canonical name. In addition to being a bit ugly, this also makes help() a bit lame: help(foo) will say that foo contains a module _foo, and only if you say help(foo._foo) do you get the documentation for MyCppClass.

Is there something I can do differently in __init__.py or otherwise to make it so Python sees foo.MyCppClass as the canonical name?

I'm using Python 2.7; it would be great if the solution worked on 2.6 as well.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • If the `_foo` module were written in Python, I'd just tell you to change your classes' `__module__` attribute (you could do this just after defining each class, or write a loop that does it all at once) but that attribute probably isn't writable on your C++ classes... Maybe there's some way to change that attribute in Boost? (Never used it myself.) – kindall Feb 24 '12 at 18:58
  • I think I can change the module name, but change it to what? I don't want to go from `foo._foo.MyCppClass` to `foo.bar.MyCppClass` - I want to end up with just `foo.MyCppClass` as the canonical name in Python. – John Zwinck Feb 25 '12 at 16:51

2 Answers2

2

I had the same problem. You can change the module name in your Boost.Python definition:

BOOST_PYTHON_MODULE(_foo)
{
  scope().attr("__name__") = "foo";
  ...
}

The help issue is a separate problem. I think you need to add each item to __all__ to get it exported to help.

When I do both of these, the name of foo.MyCppClass is just that -- foo.MyCppClass -- and help(foo) gives documentation for MyCppClass.

AndyJost
  • 1,085
  • 1
  • 10
  • 18
  • Just setting `__name__` seems to solve it for me. I tried to figure out a way to make it work entirely in the `__init__.py` file where I do `import *` but I didn't succeed. Do you know if it's possible to set `__name__` in Python if I want to avoid changing the C++ code? Thanks! – John Zwinck Jul 30 '12 at 15:01
1

You can solve the help() problem by adding the line

__all__ = ['MyCppClass']

to your __init__.py file.

Cito
  • 5,365
  • 28
  • 30
  • That's an interesting point, so thank you. However, I'm still looking for a solution to my "real" problem...fixing help() will be nice too though. – John Zwinck Feb 29 '12 at 10:24