前言

在软件工程中,我们从大的宏观方向,要看业务目标、工程架构,到具体实施时就要选择适合工程实现的编程语言和配套组件。在选择编程语言时根据项目的不同,我们可能会有很多需要考虑的因素,从编程语言本身的角度来看,他们是“大同小异”的,但如果从差异角度看,每种编程语言除了语法体现不同外,执行方式、性能、内存管理、模块组织、组件、第三方库等又会有很大差异,但这些却又是我们要需要考虑的关键点。

下面我们聊一下python语言的模块引入方式,当我们知道了其引入方式,那么组织模块就是自己的事了~~

当然,本文中不一定会列出所有引入方式,我们只关注常用的、个人认为较好的方式。

在开始聊这个话题前,我们首先要区分的概念是 package、module、class,我们粗略总结:

1. package是一个层级的概念,它通常是一个目录,在package中可能会包含多个module;

2. module是一个文件(通常是package中的文件),在文件中我们可以定义类或函数等;

3. class 类,它被包含在module文件中;

然后,对于引用格式,我们做一个“感性”的总结就是:package要用“from”,module和class要用import,如:

from package import module

import package.module    # 注意,不能这样引用:import package.module.class

基本的模块引入方式

为方便举例说明,现假设有如下目录结构及文件:

$ tree .
├── package1
│   ├── module1.py
│   └── module2.py
└── test.py$ cat package1/module1.py
class class1:def hello(self):print('I am class1 in module1')$ cat package1/module2.py
class class2:def hello(self):print('I am class2 in module2')$ cat test.py
from package1 import module1  # 方式1
from package1.module2 import class2  # 方式2  注意,不能这样引入:import package1.module2.class2module1.class1().hello()
class2().hello()

可以看到,test.py中展示了两种基本的引入模块和类的方式,并调用了hello方法。我们执行test.py,结果如下:

$ python3 test.py
I am class1 in module1
I am class2 in module2

当然我们还可以用其他方式引入模块,例如我们修改test.py文件为 :

import package1.module1
import package1.module2
from package1 import *  # 注意,前面一定要有两个import语句,否则是不正确的module1.class1().hello()
module2.class2().hello()

这种方式没有语法错误,但个人不建议用这种方式,因为不太直观。

进一步理解模块的概念

细心的你可以已经注意到,上面的目录结构中不能直接引入package1中的所有模块(from package1 import * ),这是为什么呢?

其实原因很简单:因为现在的package1还是一个普通的目录,还算不上是一个真正意义上的package,需要在package下放一个__init__.py文件来标识当前目录为一个package!

这里要说一下,我们在设计python程序的时候,只要是我们认为应该是一个package的目录都应该包含一个__init__.py文件(即使该文件为空)。

下面我们在package1目录下添加空的__init__.py文件,并修改test.py文件内容:

$ tree .
├── package1
│   ├── __init__.py
│   ├── module1.py
│   └── module2.py
└── test.py

$ cat test.py from package1 import *module1.class1().hello()module2.class2().hello()

如果此时执行test.py会发现依然报错!

这是因为,虽然此时package1是一个“package”了,但__init__.py文件内容为空(我们可以把__init__.py文件看做是一个package的“对外接口”,可以起到屏蔽“包”内细节的做用)。使用__init__.py文件一般需要注意以下两点:

1. __init__.py文件内一般使用 __all__ 关键字来限定package内对外的模块。

2. __init__.py文件尽量“轻”,即最好不要在里面定太多代码(如定义类等),虽然这样做不会报错。

下面通过修改__init__.py文件和test.py文件来分别说明__init__.py文件的使用方式:

$ cat package1/__init__.py
__all__ = ['module1', 'module2']$ cat test.py
from package1 import *module1.class1().hello()
module2.class2().hello()

# 运行脚本$ python3 test.py I am class1 in module1I am class2 in module2

当然,如果__init__.py文件内包含某个类,package外面也可以直接访问到,如:

$ cat package1/__init__.py
__all__ = ['module1', 'module2']class class3:def hello(self):print('I am class3 in __init__.py')$ cat test.py
from package1 import module1, module2, class3module1.class1().hello()
module2.class2().hello()
class3().hello()$ python3 test.py
I am class1 in module1
I am class2 in module2
I am class3 in __init__.py

注意,test.py 文件中指明了需要引入的内容 (from package1 import module1, module2, class3),如果将这个引入方式改为全部引入(from package1 import * )则会报错,因为 import * 引入的package内容需要__init__.py文件中__all__关键字指定!

当然,如果要引入具体module的所有内容,可以通过 import * 的方式,如:from package1.module1 import *

更复杂的引用

我们可以想到,引用还有很多其他情况,如不同package间、不同目录下或不同层级目录下的相互引用等。

其实,所有的引用,在了解了以上原理后都是很好了解的,不过这里还要先提一下”环境变量“,关于环境变量概念和作用这里略过。python添加环境变量的方法:

sys.path.append('user_path')  # 其中 user_path 即我们要添加的路径

添加到环境变量中的路径,在本工程中各文件中都可以直接访问到。下面我们利用和之前相似的例子进行说明。

假设我们现在有一个和package1同级的包,package2,且package2中有一个moudle3.py文件,此时package1中的module2文件需要访问package2的module3.py,文件目录及内容如下:

$ tree .
├── package1
│   ├── __init__.py
│   ├── module1.py
│   └── module2.py
├── package2
│   ├── __init__.py
│   └── module3.py
└── test.py$ cat package1/__init__.py
__all__ = ['module1', 'module2']$ cat package1/module1.py
class class1:def hello(self):print('I am class1 in module1')$ cat package1/module2.py
from package2.module3 import class3  # 这里我们引用了package2的class3
class class2:def hello(self):print('I am class2 in module2')$ cat package2/__init__.py
__all__ = ['module3']$ cat package2/module3.py
class class3:def hello(self):print('I am class3 in module3 which of package2')$ cat test.py
import sys, os
curr_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(curr_dir)  # 这里我们添加了环境变量from package1 import module1, module2module1.class1().hello()
module2.class2().hello()
module2.class3().hello()  # 通过package1的module2引用到了package2中module3下的class3

请注意其中的注释。test.py 脚本运行结果如下:

$ python3 test.py
I am class1 in module1
I am class2 in module2
I am class3 in module3 which of package2

根据我们工程的实际情况可能会有很多更复杂的情况,其原理是不变的。

转载于:https://www.cnblogs.com/wwjneu/p/9802154.html

python模块引用相关推荐

  1. python包引用问题

    python模块引用梳理 文件组织结构: 复制代码 t ├── __init__.py ├── main.py ├── t1 │ ├── A.py │ └── __init__.py └── t2 ├ ...

  2. python自己创建模块引用失败_详解Python import方法引入模块的实例 Python怎么import自己写的模块...

    python中 import导入模块失败的问题? python中的import引用不了模块我傻,为你傻;我痛,为你痛;深夜里,你是我一种惯性的回忆. 为什么我用from lianxi import*就 ...

  3. 扩展Python模块系列(四)----引用计数问题的处理

    承接上文,发现在使用Python C/C++ API扩展Python模块时,总要在各种各样的地方考虑到引用计数问题,稍不留神可能会导致扩展的模块存在内存泄漏.引用计数问题是C语言扩展Python模块最 ...

  4. python3 模块调用其他类的方法_python类的函数调用 python如何引用其他模块中类的方法中的变量?...

    python中类内部的函数可以互相调用吗? python 如何调用类的方法要遇上一个人只要用一分钟的时间:要喜欢上一个人只要用一句话的时间:要爱上一个人只要用一天的时间:但要忘记一个人却要用一生的时间 ...

  5. python模块相互引用_python导入模块交叉引用的方法

    实际项目中遇到python模块相互引用问题,查资料,终于算是弄明白了. 首先交叉引用或是相互引用,实际上就是导入循环,关于导入循环的详细说明,可见我摘自<python核心编程>第二版的摘抄 ...

  6. 遇到问题–python–pytest引用模块错误

    转载请注明出处:遇到问题–python–pytest引用模块错误 遇到问题 python项目结构如图: main.py中引用了 import pandas as pd 运行main.py文件没问题,但 ...

  7. Python接口测试-模块引用与映射

    PyCharm中发现模块引用老是有各种问题 可以用映射来解决,例如需要调用登录模块里面的东西的时,可以这样处理: 登录模块:1-login.py import this import requests ...

  8. [ 转]Python模块(二)import和from...import的区别

    Python模块(二)import和from...import的区别 听语音 原创 | 浏览:2975 | 更新:2018-04-02 13:02 | 标签:PYTHON 1 2 3 4 5 6 7 ...

  9. 如何获取本地安装的Python模块列表?

    我想获得Python模块的列表,这些模块在我的Python安装(UNIX服务器)中. 如何获得计算机中安装的Python模块的列表? #1楼 使用pkgutil.iter_modules非常简单的搜索 ...

最新文章

  1. C 语言编程 — 编程实践
  2. 如何查看AWS实例上使用的key value pair名称
  3. 高校何时开学?教育部回应
  4. Permission denied的解决办法
  5. ruby gem 安装mysql2_Ruby gem mysql2安装错误
  6. mybatis mysql 事务处理_详解Java的MyBatis框架中的事务处理
  7. 广二师的计算机专业好不,广东技术师范学院和广东第二师范学院哪一个更好?...
  8. 【maven】idea maven slf4j : StackOverflowError
  9. 【软件设计师考试】《软件设计师教程》(一)
  10. 80psi等于多少kpa_psikpa换算(kpa bar 换算)
  11. Bone Collector——01背包
  12. 模电学习笔记(十三)——控制直流偏执电路
  13. 【Python爬虫】IOS苹果商店指定APP评论爬取
  14. TikTok搬运视频怎么做,搬运怎样的视频最好
  15. 鸣人来教你安装配置JDK
  16. 如何测算BMI指数(Python)
  17. 分布式搜索引擎ElasticSearch(二)---ElasticSearch进阶使用教程
  18. 启英泰伦CI-C22GS02(ci1122)单麦离线智能语音模块制作声控小台灯
  19. 用python对股票进行可视化分析_股票分析 | 用Python玩玩A股股票数据分析-可视化部分...
  20. 2-github术语介绍

热门文章

  1. 套路、逻辑与思辨(道理的论证)
  2. AngularJS之禅
  3. AS3.0函数定义的方法
  4. 嵌入式SQL程序的VC+SQL server 2000实现的环境配置
  5. 深入探讨 Java 类加载器
  6. ASP.NET MVC Bundles 之学习笔记
  7. Git图文教程:从零到上传GitHub项目
  8. [转]---UAP中如何判断当前APP在哪个平台设备上运行
  9. sqlserver 两表联查去重_去山东省(烟台)必吃“特色”小吃 ,舌尖5大美食享受!...
  10. hdu4973 线段树(题目不错,用了点,段,更新查找还有DFS)