Reputation: 4002
Let's say I have the following structure:
And the user of the package wants to use class1 and class2.
The way I understand I have too options, in my __init__.py
:
from module1 import class1,class2
Which will let the user do something like x = pacakge.class1()
Or:
import module1
Which will let the user do something like x = pacakge.module1.class1()
Is there is a preferred way?
Upvotes: 0
Views: 580
Reputation: 77912
It really depends on the context - your package's, modules, classes, functions etc semantics, what they are used for, how they relate to one another etc, and of course the size of your package (how many subpackages / modules, how many names in each etc) - so there's no one-size-fits-all technical answer here.
If your modules are only an implementation detail (ie to avoid having one monolithic 10+k source file) and from a semantic POV some object (function, class, whatever) really belongs to the package's top-level, then use the package's __init__
as a facade so the user don't have to know where the name is effectively defined.
If your modules/subpackages make sense as coherent namespaces (like for example django.db
and django.forms
) then you obviously want to keep them clearly distinct and let the user explicitely import from them.
Also keep in mind that once a submodule or subpackage name is publicly exposed (it's existence is documented and client code imports from it) then it is de-facto part of the API and you cannot rename it / move it / move things from it without breaking client code.
NB in this last case you can still turn a module into a package used as a facade (using the packages __init__
) but the change must (well, should) be transparent to the client code.
As a general rule: start with the simplest implementation - either a plain single module if it's a small lib (only a few public names exposed) that doesn't require namespacing or a package with a few "namespace" submodules for bigger or less cohesive libs, and if your modules grow to huge turn them into subpackages using the package's __init__
to hide the fact to client code.
Upvotes: 1
Reputation: 4002
One disadvantage of the 2nd approach:
If the package has many modules, the user will have to do something like:
from package.module1 import *
from package.module2 import *
...
Which can be a little annoying.
So, here is what I think would work best:
This way, if my user wants to use the pacakage's foo
features, he can simply do from pacakge.foo import *
and get foo
and only foo
features.
Upvotes: 0