python编程中的circular import问题

循环引入,circular import是编程语言中常见的问题,在C语言中我们可以使用宏定义来处理,在c++语言中我们可以使用宏定义和类的预定义等方式来解决,那么在python编程中呢?

其实在python编程语言中出现circular import的时候还是毕竟少的,主要原因是python用来开发较大、较复杂的项目的场景有限,这一点不像C、C++等语言,但是随着AI领域的兴起python语言作为几乎是唯一的选择慢慢的应用多了起来。与此同时如网络编程、图形设计等中小规模的开发场景也开始逐渐选择python语言了,毕竟python语言的用户多了以后一些适合python的中小级别项目也会更倾向选择使用python语言开发了,但是随着python开发的项目大了起来以后这个circular import问题也就开始常见起来了。

=====================================

给出一个circular import的典型例子:

x2.py

print("this is x2.file, in ")

import x3

def f1():
    print("x2.f1")

def f2():
    x3.f3()

f2()

print("this is x2.file, out ")

x3.py

print("this is x3.file, in")

import x2

def f3():
    print("x3.f3")

def f4():
    x2.f1()

f4()

print("this is x3.file, out")

运行结果:

python编程中的circular import问题

python编程中的circular import问题

从上面运行的代码可以看出,循环导入问题简单地说就是,当一个python模块文件运行到导入语句时,它会跳转到另一个模块文件并执行该模块文件,而跳转到该模块文件则会导入之前未完成的模块文件。但是,由于原来的模块文件已经被添加到介绍模块中,不会再次导入,并且因为执行被中断并跳到当前模块,所以它没有完全运行。也就是说,在跳转后的模块文件查询中已经引入的模块发现原来的模块已经被引入(但是原来的模块此时还没有完全引入),不会重新引入原来的模块,但是此时跳转模块调用了原来模块中的变量,并且因为原来的模块没有完全引入,所以变量不能被成功调用,此时会打包循环导入的错误。

[En]

From the above code running, we can see that the circle import problem is simply that when a python module file runs to an import statement, it jumps to another module file and executes the module file, and the jump to the module file import the previously unfinished module file. However, because the original module file has been added to the introduction module will not import again and because the execution was interrupted and jumped to the current module, it did not run completely. In other words, the module that has been introduced in the module file query after the jump finds that the original module has been introduced (but the original module has not been fully introduced at this time) and will not reintroduce the original module, but at this time the jump module calls the variables in the original module, and because the original module is not fully introduced, the variable cannot be called successfully, and the error of circle import will be packaged at this time.

知道了circle import 问题出现的原理,那么像上面的例子我们完全可以通过简单的修改import的位置来解决,给出修改后的文件:

x2.py

print("this is x2.file, in ")

def f1():
    print("x2.f1")

import x3

def f2():
    x3.f3()

f2()

print("this is x2.file, out ")

x3.py

print("this is x3.file, in")

def f3():
    print("x3.f3")

import x2

def f4():
    x2.f1()

f4()

print("this is x3.file, out")

运行结果:

可以看到对于circle import,只要解决对未初始化变量的调用就会解决报错问题,像上面的例子就是通过修改import的时机来解决的,但是在实际coding中出现circle import的情况都很复杂,对于不同情况也都需要不同的解决方法,但是基本准则就是解决对未初始化变量的调用。

python3 main.py

python编程中的circular import问题

python3 main.py 时,xyz模块在main.py中被执行所以在y.py中import xyz时就不会被再次执行,但是此时main.py中对xyz模块的执行并没有完成因此y.py中调用xyz.fun就会由于未初始化而报错。

python3 xyz.py 时,xyz模块作为启动模块不会在启动时加入到已经在已经import的模块的路径集合中,所以在y.py中import xyz时就会被再次执行,这时再次跳转到xyz.py文件中,而由于y.py已经加入到已经import的模块的路径集合中,因此此时执行xyz.py模块可以顺利的对xyz.fun初始化,然后xyz执行完重新回到y.py中执行对xyz.fun的调用就不会报circle import的错误。

circle_import_python_1进行下修改,得到circle_import_python_2代码,修改的地方在submodule/init.py中的s=0的声明位置,我们将submodule/init.py中的s=0的声明位置放在import语句后。

修改后的 submodule/init.py :

print("this is __init__, in")

import submodule.x
import submodule.y

s = 0

print("this is __init__, out")

执行:

python3 xyz.py

python编程中的circular import问题

您可以看到,这也是一个圆导入错误。在蟒蛇中,如果项目越大,圈子导入的机会就会增加。了解圈内进口的原则,我们可以根据实际情况进行处理。如前所述,一旦有循环导入,如果没有解决方案,可以选择最后的方法,也就是代码重构,但重构需要大量的时间和时间,另外一种会影响原代码的逻辑结构和风格。

[En]

You can see that it is also a circle import error. In python, if the project is bigger, the chance of circle import will increase. Knowing the principle of circle import, we can deal with it according to the actual situation. As mentioned earlier, once there is circle import, if there is no solution, you can choose the final method, that is, code refactoring, but refactoring requires a lot of time and time, and the other will affect the logical structure and style of the original code.

可以说,对于circle import问题最好的解决方法就是在coding时对模块的层级做到较好的计划,在coding时有较好的规范可以很好的避免circle import问题的出现,不过在有些情况下该问题又难以通过改善coding规范的方法来解决(当然可以通过重构的方法来解决,不过需要尽量避免重构),给出以下的例子,参见:

https://www.bilibili.com/video/BV1E54y1R7wm/?vd_source=f1d0f27367a99104c397918f0cf362b7

类似的代码是参考上面视频中的代码重写的,并上传到:

[En]

The similar codes are rewritten with reference to the code in the video above, and uploaded in:

circle_import_python_3

x_class.py

python编程中的circular import问题

y_class_3.py

python编程中的circular import问题

对这个 typing. <span class="highlighted">TYPE_CHECKING</span> 个人理解的不是很多,个人的理解是 typing. <span class="highlighted">TYPE_CHECKING</span> 在编译时为true,在运行时为false。因此在编译时可以正常通过,在代码编辑时可以被识别出类型并给出很好的提示信息(value: int),而在执行时由于 typing. <span class="highlighted">TYPE_CHECKING</span> 为false,所以在执行时并不会执行import class语句因此不会造成circle import的错误。

而在y_class_1.py和y_class_2.py中虽然可以通过编译及运行,但是在代码编辑时还是会提示类型无法识别:

python编程中的circular import问题

可以看到y_class_1.py和y_class_2.py中所使用的方法可以起到对程序员的提示功能,但是并不被IDE所识别,y_class_3.py中所使用的 typing. <span class="highlighted">TYPE_CHECKING</span>方法为python的原生支持语法可以被IDE所识别。

Original: https://www.cnblogs.com/devilmaycry812839668/p/16447208.html
Author: Death_Knight
Title: python编程中的circular import问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/7360/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

发表回复

登录后才能评论
免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部