Eliy Arlev
Eliy Arlev

Reputation: 578

controlling namespaces while importing modules in python

I have split a project that i write from 1 file to several files The thing is, that i have around 50 classes that I created and are called from the main file, I don't want to rewrite all those class references and add the module name before each class.

I tried to make all those classes accessible through 1 package (Tokens)

So I have

Main.py
Tokens / 
   __init__.py
   Gen.py
   BuilltIns.py

The Idea was to populate the package namespace with all the classes, and then import the package inside Main.py

__init__.py:
from Gen import *
from BuilltIns import *

Main.py:
from Tokens import *

When I ran __init__ it works perfectly, and dir() reveals that all class names are imported to package namepace.

However, when i run Main.py, I get the error message:

Traceback (most recent call last):
  File "../Main.py", line 1, in <module>
    from Tokens import *
  File "..\Tokens\__init__.py", line 1, in <module>
    from Gen import *
ModuleNotFoundError: No module named 'Gen'

How should I extract the 60+ classes from Main.py to other modules without rewriting all the calls for those classes?

Upvotes: 0

Views: 244

Answers (1)

a_guest
a_guest

Reputation: 36249

You should use from Tokens.Gen import ... since Tokens is the package where the Gen module resides. The import path should be relative to the main script, unless you've modified the sys.path to specify additional directories to be searched during imports.

Alternatively, in Tokens/__init__.py you can do from .Gen import * (note the . before Gen). This denotes a relative import. What happens when you run the main script is that the current working directory is added to the paths to be searched during imports, so when from Gen import ... is encountered only the default locations are searched (which doesn't include the Tokens directory). By using a relative import you tell Python where it can find that module relative to the current one.

Note that you can define your classes in __all__ in order to constrain what will be imported during from ... import *. This way you don't leak other names in your main script's namespace.

Upvotes: 1

Related Questions