Python: Importing a Sub‑Package or Sub‑Module

Python: importing a sub‑package or sub‑module

You seem to be misunderstanding how import searches for modules. When you use an import statement it always searches the actual module path (and/or sys.modules); it doesn't make use of module objects in the local namespace that exist because of previous imports. When you do:

import package.subpackage.module
from package.subpackage import module
from module import attribute1

The second line looks for a package called package.subpackage and imports module from that package. This line has no effect on the third line. The third line just looks for a module called module and doesn't find one. It doesn't "re-use" the object called module that you got from the line above.

In other words from someModule import ... doesn't mean "from the module called someModule that I imported earlier..." it means "from the module named someModule that you find on sys.path...". There is no way to "incrementally" build up a module's path by importing the packages that lead to it. You always have to refer to the entire module name when importing.

It's not clear what you're trying to achieve. If you only want to import the particular object attribute1, just do from package.subpackage.module import attribute1 and be done with it. You need never worry about the long package.subpackage.module once you've imported the name you want from it.

If you do want to have access to the module to access other names later, then you can do from package.subpackage import module and, as you've seen you can then do module.attribute1 and so on as much as you like.

If you want both --- that is, if you want attribute1 directly accessible and you want module accessible, just do both of the above:

from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works

If you don't like typing package.subpackage even twice, you can just manually create a local reference to attribute1:

from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works

Python import module from within module in another subpackage

This is because python doesn't know where to find main_package in script_a.py.

There are a couple of ways to expose main_package to python:

  1. run script_a.py from main_package's parent directory (say packages). Python will look for it in the current directory (packages), which contains main_package:

    python main_package/folder_1/folder_2/script_a.py
  2. add main_package's parent directory (packages) to your PYTHONPATH:

    export PYTHONPATH="$PYTHONPATH:/path/to/packages"; python script_a.py
  3. add main_package's parent directory (packages) to sys.path in script_a.py

    In your script_a.py, add the following at the top:

    import sys
    sys.path.append('/path/to/packages')

cannot import submodule from a module

If you want to be able to say ...

from object_detection.utils import utils_image

... then clearly the utils directory must be a subdirectory of the object_detection directory and not a sibling directory, i.e. at the same level.

Now for your other error:

ImportError: attempted relative import with no known parent package

You did not really specify under what circumstances you get this error other than saying "Running above init.py files gives me an error:". But how are you "running" these py files or what does that even mean?

If you are executing a script when this occurs (how else would you be getting this error?), the script must be invoked as a module (because scripts cannot have relative imports -- see below) as follows (we will assume that the script you are trying to execute is test_utils_image.py):

First, the parent directory of object_detection, which is Object_Detection, must be in the system path of directories to be searched for finding modules and packages referenced in import statements. In general, this can be accomplished several ways, for instance

  1. The script you are executing is in Object_Detection (the directory of the script is automatically added to the sys.path list of directories to be searched by the interpreter).
  2. Dynamically appending Object_Detection to the sys.path list of directories at runtime by your script.
  3. Appending Object_Detection to the PYTHONPATH environment variable.

Item 1 above would not be applicable for this specific case since the module we are executing by definition is not in the Object_Detection directory.

Note that if your classes will eventually be installed with pip, then site-packages will be the parent directory of object_detection, which is already in sys.path.

Then you can execute your script as:

python -m tests.test_utils_image

If you want to execute this .py file as a script, for example by right-mouse clicking on it is VS Code, then see Relative imports for the billionth time, in particular the section Scripts can't import relative, which says it all -- it cannot work!

To invoke this as a script, just convert the relative imports to absolute imports. In fact, the PEP 8 Style Guide says:

Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on sys.path):

Python subpackage import no module named x

Your directory structure should be

package (choose whatever name you want for the high-level package name)
__init__.py
a.py
subpackage
__init__.py
b.py

The parent directory of package needs to be in the sys.path list of directories to be searched for resolving imports. This can be accomplished by having that directory being the current working directory when you invoke whatever program you are running or adding the directory to the PYTHONPATH environment variable or modifying sys.path at runtime before doing your imports.

Then a.py should be either:

from package.subpackage.b import classX

or

from .subpackage.b import classX


Related Topics



Leave a reply



Submit