Reputation: 41
I have a little internal DSL written in a single Python file that has grown to a point where I would like to split the contents across a number of different directories + files.
The new directory structure currently looks like this:
dsl/
__init__.py
types/
__init__.py
type1.py
type2.py
and each type file contains a class (e.g. Type1
).
My problem is that I would like to keep the implementation of code that uses this DSL as simple as possible, something like:
import dsl
x = Type1()
...
This means that all of the important symbols should be available directly in the user's namespace. I have tried updating the top-level __init__.py
file to import the relevant symbols:
from types.type1 import Type1
from types.type2 import Type2
...
print globals()
the output shows that the symbols are imported correctly, but they still aren't present in the caller's code (the code that's doing the import dsl
). I think that the problem is that the symbols are actually being imported to the 'dsl' namespace. How can I change this so that the classes are also directly available in the caller's namespace?
Upvotes: 4
Views: 7478
Reputation: 11
@Eli, @Daniel thanks for the "aha" answer. I was almost there but needed the extra nudge...
Basically the solution was split into two stages: to use the package initialiser to pull the 'exported' second-level symbols into the top-level dsl
package (this bit I already had) and then to pull those symbols into the caller's code with from dsl import *
. This makes sense as the caller should really have control over what they pull into their namespace.
from pkg import *
seems to be generally frowned on, but in this case I think it's a reasonable solution as the number of symbols exported by my package will be limited.
Upvotes: 1
Reputation: 18754
This is what I would do
In dsl/init__.py, add
def import_symbols(namespace):
namespace['type1'] = dsl.types.type1
namespace['type2'] = dsl.types.type2
From the caller, do
import dsl
dsl.import_symbols(globals())
No only can you import symbols from a second level package into your current namespace, by defining you own import_symbols()
, you also have more explicit control on which symbol to import rather than importing everythin with import *
.
Upvotes: 2
Reputation: 599490
You can't do that. It's up to the user what they import into their own code. If they want to import everything into their namespace, they can do from dsl import *
, but you can't dictate this.
Upvotes: 0