Python imports one subpackage without the other

I have the following package structure

package __init__.py sub1 __init__.py foo.py # Contains class Foo sub2 __init__.py bar.py # Contains class Bar 

I want to be able to just import package and have package.Foo and package.Bar , i.e. I want subpackages to be transparent to users.

The trick is that importing sub2 is time consuming and many users don’t care about things in sub2 at all and only want things in sub1. Thus, I want users to be able to say import package.sub1 or from package import sub1 only import sub1 and skip import sub2.

I know I can reach the first part if package/__init__.py contains

 from .sub1 import * from .sub2 import * 

and has package/sub1/__init__.py be from .foo import Foo and similarly for sub2. However, this will always import sub1 and sub2, even if the user only tries to import package.sub1 .

Accordingly, I can achieve the second part by getting package/__init__.py empty and using the same sub1/__init__.py as above. However, simply saying import package does not load sub1 or sub2, so users will need to explicitly load them, and then refer to package.sub1.Foo .

Ideally, the solution will work in both 2.7.10 and 3.5.0, but I will agree with one or another if both options are impossible.

+5
source share
2 answers

The LazyLoader class LazyLoader provided for this situation: deferring module loading when it is actually used, instead of the import item.

To create a lazy bootloader, you can follow the example in the documentation:

 suffixes = importlib.machinery.SOURCE_SUFFIXES loader = importlib.machinery.SourceFileLoader lazy_loader = importlib.util.LazyLoader.factory(loader) finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)]) 

then you can use finder.find_spec to get the module specification and pass the result to Loader.create_module to load it.

This is a little cumbersome to do manually for only one module.

Note that looking for “lazy python imports” you will find many solutions that have different pro and cons, some of which run in python2.x. However, the LazyLoader class above is the official way to do this in python3.5 +

+4
source

you can add your shortcuts to __init__.py your module:

package / __ __ INIT. RU

 __all__ = [ ... add everything you want to be listed for this module 'Foo', 'Bar', ... ] from package.sub1.foo import Foo from package.sub2.bar import Bar 

now you can call:

 from package import Bar 
0
source

Source: https://habr.com/ru/post/1234916/


All Articles