上一次我们介绍了《Python的模块module介绍》,主要包括模块的基本概念、模块的搜索路径sys.path和PYTHONPATH、如何离线非管理员安排第三方模块包、源码安装Tk库等。由于时间较长,忘记的童鞋可以点击回顾一下。
我们在做项目时,通常希望把一些常用的独立的功能做成一个“公用库”,方便下次需要时直接“调库”。还有些时候,我们发现为了兼容很多特殊情况,脚本越改越长,越改越乱。这时我们希望把单个长脚本拆成几个短小的模块,更方便维护。
为了解决这些问题,今天就来讲讲如何写自己的模块和包。
这篇文章主要包括以下内容:
如何写自己的模块
如何写自己的包
一开头提到我们希望实现一个公用库,把经常用到的数据和函数都放进去。而python的模块正是为此而设计。
以仿真脚本为例,所有的项目都会用到“读取RTL文件”和“读取仿真verilog模型”这两个功能。所以我们就把这两个功能做成单独的模块。
如上图,通过这种方法,把公用的函数get_rtl_files()、get_verilog_model()移到sim_lib.py里。顶层的仿真脚本sim.py里就只有config file、cmd字符串拼接等功能了。这样看起来我们的仿真脚本就清爽了许多。
除了写好sim_lib.py和sim.py,我们还要注意文件摆放的位置。一般情况下,我们可以把两个py文件放在同一个目录下。如下所示。
然后运行python sim.py即可。运行时,python会在当前目录找到sim_lib.py,然后作为库import进去。下图是运行后的log,可以看到已经拼接好cadence IES的启动命令和参数了。
简单的说,模块的包就是把一堆的模块按照一定的层次关系放到一个目录结构里。我们把这整个目录称为包(Package)。
我们先来看看python自带的包是什么样子的。下图是python安装目录里的tkinter,我们看到目录下有很多.py文件和子目录test,子目录test下也是类似的结构。
我们看到,每级目录下有一个__init__.py文件。这个文件的在import tkinter时被执行。我们举个例子,建立test.py和一个目录mylib,mylib下新建__init__.py文件。如下:
测试结果如下:
$ python test.py
mylib is imported
下面我们再来看一个复杂一点的例子,模仿tkinter来写一个自己的包。比如我们有lint_lib.py、sim_lib.py、sim_post_lib.py打算分成两个目录存放,一般项目文件多了后按目录存放看起来比较清楚。
我们来建立目录结构,如下。并把lint、sim、sim_post三个模块放进去。再为每个目录创建一个__init__.py文件,__init__.py先为空。这样我们的包mylib就可以使用了。
这三句都可以正常执行。
大家有没有觉得mylib.sim_libs.sim_lib太长?是的,python提供了更好的方法。比如:
这样就简洁多了。
好了,核心内容就介绍完了,感兴趣的可以下载本文中的三个例子做下练习。
关于模块和包还有很多细节和高级用法,这里先不做深入。后面实际用到时再介绍。