导读:前段时间想用c++写有限元程序,最终由于我个人在c++上的造诣比较差,又希望有灵活的表现形式,只能转向了python。

问题:花了三天的时间重新构建了我的有限元程序,在写测试案例的时候,发现一个Python导入模块的顺序引发的一个错误。

我在__init__.py 文件中,import包时,没有注意顺序,结果在后面文件中使用from XX import * 时,会出现找不到相应库的错误。




import python安装的module 显示找不到 python import找不到文件_加载


1、DinoFem 包

2020年初我在家的时候,想给儿子写一个游戏,于是为了学习pygame,就写了一个教程,也就是我的专栏里的那个《Pygame视频教程》。里面封装了pygame,起了个新的名字叫Dino。因为儿子喜欢恐龙。

这次,我自己开始开发Fem通用框架,也使用了这个名字,叫DinoFem。

这个问题就是在开发DinoFem包的过程中发现的。

2、在python包中使用__all__ 变量

一个包,比如就叫DinoFem,是一个文件夹,里面有一个__init__.py文件。这个__init__.py文件可以为空。也可以增加一些代码,用以进行在加载包时所做的操作。例如,我们的__init__.py文件是这样的内容。


import python安装的module 显示找不到 python import找不到文件_python_02


也就是,我们先import一些类和函数,然后将这些函数名放在__all__这个列表里。在其他地方调用的时候,我们可以使用

from DinoFem import *

这样,我就可以导入__all__列表里的所有的函数和类或者变量了。

3、加载顺序的坑

#python#

我加载了类,为什么调用的时候还是找不到呢?

在有些地方我发现,即使我使用了这个

from DinoFem import *

并且在__all__列表里已经加入了要加载的类,但是还是会出现

NameError: name 'Mesh‘ is not defined

因为我是DinoFem包的第一次迭代,所以其实有很多错误,而这个错误是藏的很深的。当我一个一个的排除之后,还是出现了这个错误。经过了1个小时的排查,终于发现了这个隐藏的问题。最终,还是我学艺不精啊。

果真应了那句名言啊:

任何人,都只能赚到自己认知范围内的钱

不然就要付出生命的代价。

__all__列表里顺序是有讲究的,必须是包的子模块中使用的元素已经被定义过。否则,就会出现"not defined"错误

4、测试案例

我们设计了一个简单的案例,如图,定义了一个包DPG,里面有四个文件


import python安装的module 显示找不到 python import找不到文件_有限元_03


# a.pydef func_a():    print("file a have a function func_a")
# b.pyfrom DPG import *def func_b():    func_a()    print("file b have a function func_b")
# c.pyfrom DPG import *if __name__ == '__main__':    func_b()
# __init__.pyfrom DPG.b import func_bfrom DPG.a import  func_a__all__=[    'func_b',    'func_a']

我们运行c.py文件后,就出现了错误提示


import python安装的module 显示找不到 python import找不到文件_python_04


这个错误就是我们所说的import顺序引发的错误。

我们是不是只需要把__all__里的顺序调整了就可以了呢?

我们把__init__.py文件的__all__列表中加载顺序调整了之后,运行,依然出现找不到定义的错误。

我们需要把import顺序和__all__的顺序都要调整过来,才能保证程序正常调用

正确的方式应该是

# __init__.pyfrom DPG.a import  func_afrom DPG.b import func_b__all__=[    'func_a',    'func_b',]

c.py的运行结果为:

file a have a function func_a

file b have a function func_b

结论

对于没有系统学习过python的朋友来说,会遇到非常多的坑。这也是在2020年初,疫情在家的时候,写了很多微头条来说明python的技巧和一些坑的原因。大概也是为了完善我自己的python编程知识吧。

彩蛋

我的DinoFem程序的整体框架已经有了初步的雏形了,现在只能计算1D的问题。希望有兴趣的朋友,可以参与进来。

以下是整体的框架


import python安装的module 显示找不到 python import找不到文件_python_05


代码的文档使用pydoc生成:


import python安装的module 显示找不到 python import找不到文件_加载_06


目前完成的部分,做了一个测试,使用了我师兄在《有限元编程课程》里使用的1D的案例。误差估计和阶的估计如下图:


import python安装的module 显示找不到 python import找不到文件_加载_07


这个结果,显示了非常好的2阶精度的效果。当然这个太过简单。

后续我将持续的推进这个开发,从1D慢慢写到2D、3D。

我是张麟博士,谢谢大家的关注和支持。