> Code of our project has split into several packages and we deploy the
> project using buildout.
> All worked fine until I need to dynamically inspect python modules.
Entirely by luck, I'd say :)
> ├───project.api.config
> │ ├───project
> │ │ └───api
> │ │ └───config
> │ │ └───settings
> │ └───project.api.config.egg-info
> ├───project.api.contacts
> │ ├───project
> │ │ └───api
> │ │ └───contacts
> │ │ ├───importer
> │ │ └───views
> │ └───project.api.contacts.egg-info
> Regular code like "import project.api.config" worked fine, but now I'm
> tryed
> __import__('project.api.config'):
>
> $ bin/python
>
>>>> import project.api.config
>>>> __import__('project.api.config')
> <module 'project from
> 'c:\users\ad\project\src\project.api.contacts\project\__init__.pyc'>
You can't use dots neither in module names nor package names as they're
identifiers [1]. It's like trying to use an attribute named 'foo.bar': you
can handle it with getattr/setattr, but normal attribute access won't work:
py> x.foo.bar = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
py> setattr(x, 'foo.bar', 1)
py> x.foo.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: X instance has no attribute 'foo'
py> getattr(x, 'foo.bar')
1
[1] http://docs.python.org/reference/simple_stmts.html#the-import-statement
> What's wrong? We really need to split the code for several eggs and want
> that all of our package's names starts from 'project.api'
The only sane solution is to avoid using dots in package names. Sorry, but
having project.api.config, project.api.contacts as directory names is
simply crazy.
Looks like you actually wanted to use this layout:
project/
api/
config/
...
contacts/
...
core/
...
but made a wrong turn in the road...
--
Gabriel Genellina
> If someone is interesting - __import__ works but imp doesn't.
> In my example:
>>>> m = __import__('project.api.config')
>>>> m
> <module 'project from
> 'c:\users\ad\project\src\project.api.contacts\project\__init__.pyc'>
>>>> m.api
> <module 'project.api from
> 'c:\users\ad\project\src\project.api.contacts\project\api\__init__.pyc'>
>>>> m.api.config
> <module 'project.api.config'
> from'c:\users\ad\project\src\project.api.config\project\api\config\__init__.pyc'>
>
> Please note that the m and m.api pointed to first installing package with
> namespace project.api but m.api.config have pointed to the proper file.
>
> And releasing code with several distributions it is one of goals of
> Distribute. And you might look to pypi for... zope. There is lot of
> package
> which names starts from "zope."
> It's really convenient
Those are called namespace packages. Zope and Plone (ab)use them
extensively. The intended usage is to break up a big, monolithic package
[0] in parts that can be distributed independently. To implement a
namespace package, you need an empty __init__.py file with only these
lines [1]:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
But think carefully if you really need namespace packages; they solve a
specific problem, aren't a general purpose technique. See [2] for a
discussion.
[0] Think of a huge behemoth with a "Z O P E" sign on both sides :)
[1] http://docs.python.org/library/pkgutil.html
[2] http://weblion.psu.edu/news/are-we-overusing-namespace-packages
--
Gabriel Genellina