Home >Backend Development >Python Tutorial >An introduction to how to avoid circular import methods in Python

An introduction to how to avoid circular import methods in Python

巴扎黑
巴扎黑Original
2017-09-16 10:07:481488browse

In large-scale Python projects, due to improper architecture design, mutual references between modules may occur. The following article mainly introduces you to relevant information on how to avoid Python's circular import problem. Friends in need can refer to it. Let's take a look together.

Preface

When using packages in Python, circular import problems are very common. We created the following package to illustrate this problem:


pkg
 ├── __init__.py
 ├── module_a.py
 └── module_b.py

Among them,

__init__.py specifies pkg as a Python package

module_a.py defines one action_a()Function, which refers to an attribute in module_b.py, such as a function or variable

module_b.py defines an action_b() Function, which refers to an attribute in module_a.py, such as a function or variable

In this case, circular import error# will be thrown when the package is executed. ##Error, that is, circular reference, because module_a tries to introduce module_b, and module_b first introduces module_a, which will cause the Python interpreter to be unable to execute.

However, we can use some clever methods to make the above logic work properly while avoiding errors introduced by loops.


So, when does it work properly, when does it not work properly, and what are the reasons for those cases where it does work properly?


When will it work?

1. Introduce at the top of the module, do not use from, relative introduction, only valid in Python 2

In the module Top import, such as

import another_module, the function in module refers to the function or variable in another_module in the way of another_module.attribute. The reason why this method is effective is that import another_module is a relative reference based on the current directory, and it is an implicit reference. If the module is imported from another package, it will become invalid. In addition, the syntax import another_module is no longer supported in Python 3, so do not use this method in your code to avoid loop introduction.

For example:


# pkg/module_a.py 
from __future__ import print_function
import module_b
 
def action_a():
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import module_a
 
def action_b():
 print(module_a.action_a.__name__)

2. Import at the top of the module, do not use from, absolutely import

When importing at the top of the module, use the absolute path starting from the package, such as

import package.another_module, and the functions in the module are in the form of package.another_module.attribute Reference functions or variables in another_module, etc. The reason why it is necessary to hang up the package name to import is because import .another_moduleThis form of "relative import" will report a syntax error, while hanging up the absolute import of the package is supported by Python 2 and 3

Case:


# pkg/module_a.py
from __future__ import print_function
import pkg2.module_b
 
def action_a():
 print(pkg2.module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
import pkg2.module_a
 
def action_b():
 print(pkg2.module_a.action_a.__name__)

3. Introduce the attribute of another module at the bottom of the module instead of another module, use from

Import at the bottom of the module (at least after the referenced attribute), directly introduce the attribute of

another module, such as from package.another_module import attribute, relative import is also supported, such as from .another_module import attribute, the function in the module can directly use the referenced attribute.

For example:


# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 print(action_b.__name__)
 
from .module_b import action_b
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 print(action_a.__name__)
 
from .module_a import action_a

4. When introduced at the top of the function, you can use from

Import at the top of the function of the module, such as

from package import another_module, relative import is also supported, and either module or attribute can be introduced.

Such as:

##

# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from . import module_b
 print(module_b.action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
 
def action_b():
 from . import module_a
 print(module_a.action_a.__name__)

or

# pkg/module_a.py
from __future__ import print_function
 
def action_a():
 from .module_b import action_b
 print(action_b.__name__)
 
 
# pkg/module_b.py
from __future__ import print_function
def action_b():
 from .module_a import action_a
 print(action_a.__name__)

This way although Python 2 and 3 are supported, but the coding is not elegant enough and affects the readability of the code. It is not recommended to use


Note
## The issue discussed in this article is how to avoid loop introduction when calling a package in Python

When a Python module is executed directly on the command line, the applicable situation is not exactly the same

The above is the detailed content of An introduction to how to avoid circular import methods in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn