15

I have a plugins package that contains several modules, each defining one class (each class is a plugin).

My package structure looks like this :

plugins
├ __init__.py
├ first_plugin.py
├ second_plugin.py
└ third_plugin.py

And a plugin file typically looks like this, only containing a class definition (and a few imports if necessary) :

# in first_plugin.py

class MyFirstPlugin:
    ...

I would like the end user to be able to import a plugin like so :

from plugins import FirstPlugin

instead of having to also type the module name (which is what is currently required to do) :

from plugins.first_plugin import FirstPlugin

Is there a way to achieve this by re-exporting the modules' classes directly in the __init__.py file without having to import everything module by module like so (which becomes cumbersome when there are lots of modules) :

# in __init__.py

from .first_plugin import FirstPlugin
from .second_plugin import SecondPlugin
from .third_plugin import ThirdPlugin
Ewaren
  • 1,343
  • 1
  • 10
  • 18
  • Since all your plugins are in a package, my answer to [How to import members of all modules within a package?](https://stackoverflow.com/questions/14426574/how-to-import-members-of-all-modules-within-a-package) might help. – martineau Feb 27 '20 at 20:58
  • I have the same problem. Just wondering if you figured out and found a solution to this? – Amirsalar Aug 04 '21 at 22:15
  • I didn't really find anything satisfying... I think I had a few ideas of "hacks" using `dir()` and filtering by module name (which can be accessed as a `str` in Python), but it quickly gets dirty. – Ewaren Aug 05 '21 at 09:09
  • Sigh... Another problem is that linters will complain about `from .first_plugin import FirstPlugin` in `__init__.py`, because `FirstPlugin` isn't used. – Eric Duminil Feb 24 '23 at 22:02

2 Answers2

2

I do not think this is possible in Python. However you can import entire modules so you do not have to import each class individually.

For example

from first_plugin import *

Allowing you to do

from plugin import # Anything in first_plugin

Its kinda a pain but writing libraries is not easy (wait till you use CMake with C/C++, you have to specify every single file in your source tree :D)

Object object
  • 1,939
  • 10
  • 19
  • I think that the syntax for importing the whole plugin (while still simplifying the path) is rather `from first_plugin import *`, isn't it ? with your syntax I believe that you must still type `from plugins.first_plugin import ...` right ? – Ewaren Feb 27 '20 at 20:20
  • 1
    Crap your right, sorry im tired ill edit it to add that. Also if you want to use the `*` to import all from your library you should define a list called `__all__` with the module names to be auto imported with `*` – Object object Feb 27 '20 at 20:26
0

I think you could elaborate on answers of this post: How to import all submodules?

For example with pkgutil.walk_packages(__path__) you'd have a list of modules. Then you could use dir on the loaded module and import the results (filtering elements starting with __

rolf82
  • 1,531
  • 1
  • 5
  • 15
  • But still that would import only the submodules if I'm not mistaken, whereas I want to import the classes that are defined in the submodules. – Ewaren Feb 27 '20 at 20:52
  • If you use dir on the modules then you will have the names of the classes. I’m pretty sure that you can import them with their name. I can’t try it now but I’ll try tomorrow if you haven’t figured it out until then. – rolf82 Feb 27 '20 at 21:24