Python 2.7 学习笔记 模块和包
我们来考虑下如下几种场景:
1、编写一个python程序,如果程序比较简单,则可以把代码放到一个python文件中。但如果程序功能比较多,可能需要多个python文件来组织源代码。而这些文件之间的代码肯定有关联,比如一个文件中的python代码调用另一个python文件中定义的函数。
2、我们编写程序,肯定不会所有的东西都自己写,不会全部重造轮子,我们肯定会用到Python提供的一些标准库。那怎么使用呢?其实前面的文章中已经看到了,用import语句。 如同java中用import,c#中用using语句。
3、我们自想编写一个公共代码,或从外部找到一个第三方的公共代码,如何放入到整个python系统中,如何被自己编写的代码使用。
上面这些场景,都是在编写程序时常见的事情。
这些问题,python是通过模块和包的机制来解决的。
简单的说,一个模块就是一个python文件,一个包是包含一组模块。下面我们通过实际的例子来说明。
一、案例1:一个最简单例子
编写 test1.py文件,代码如下
#coding=utf-8
import test2
print "hello"
test2.fun("world")
编写test2.py文件,代码如下
#coding=utf-8
def fun(para):
print para
这两个python文件位于同一目录,但不一定要在python的相关系统目录下,可以是任意的合法目录。
这时我们执行 test1.py,可以成功运行。
可以看出,test1.py中的代码 调用了 test2.py中的 fun方法,这能够调用的关键是在test1.py中 import test2这个语句,表示将test2.py这个模块引入进来,
同时调用时是通过 模块名.函数名 调用的。
二、案例2: 如何放置模块
上面的例子,是两个python文件位于同一目录下。如果test2.py想放在其它目录下怎么办呢?
这里关键是让python解释器能找到 test2.py。
这种情况很常见,比如 test2.py是个通用的模块,可以被多个程序使用,那它就不能与使用它的程序放在一起,否则就要拷贝多份了。
将test2.py 放在其它地方,有多种方法,下面分别介绍。
方法一:放在python已有的系统目录下
把模块(python文件)放在python的系统目录下,引入模块时,python解释器就能找到。
可以通过如下的代码查看当前有哪些系统目录:
>>> import sys,pprint
>>> pprint.pprint(sys.path)
['',
'C:\\Python27\\lib\\site-packages\\pip-7.1.2-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\paramiko-1.15.2-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\robotframework_sshlibrary-2.1.1-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\ecdsa-0.13-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\selenium-2.47.1-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\decorator-4.0.2-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\easyprocess-0.1.9-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\webtest-2.0.20-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\beautifulsoup4-4.4.1-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\waitress-0.8.10-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\webob-1.5.1-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\six-1.10.0-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\jsonpointer-1.10-py2.7.egg',
'C:\\Python27\\lib\\site-packages\\jsonpatch-1.12-py2.7.egg',
'C:\\Windows\\system32\\python27.zip',
'C:\\Python27\\DLLs',
'C:\\Python27\\lib',
'C:\\Python27\\lib\\plat-win',
'C:\\Python27\\lib\\lib-tk',
'C:\\Python27',
'C:\\Python27\\lib\\site-packages',
'C:\\Python27\\lib\\site-packages\\win32',
'C:\\Python27\\lib\\site-packages\\win32\\lib',
'C:\\Python27\\lib\\site-packages\\Pythonwin']
python的 标准库 sys模块中的path对象包含了所有的系统路径,利用 pprint模块中的pprint方法可以格式化的显示数据,如果用内置语句print则只能在一行显示所有内容,查看不方便。
我们只要把python文件(如本文例子中的test2.py)放在上述任何目录下,python解释器就能找到。
注意:必须直接放在上述目录下,不能建立子目录,放在子目录下。要想能放到子目录下,就是包的概念,下面会介绍。
方法二:新增系统目录
除了python自己默认的一些系统目录外,应用程序也可以通过代码添加系统目录。
因为系统路径是存在 sys.path对象下的,path对象是个列表,就可以自己通过代码往其中插入目录,如
sys.path.append("D:/demo/python/dir")
但很显然,插入的这个目录作为系统目录只能对当前程序生效,因为这只是在内存中生效。
方法三:设置环境变量
如果我们不想把代码放在python的系统目录下,以免和python的目录混在一起,增加管理的复杂性。
甚至有的时候,因为权限的原因,还不能在python的系统目录下加文件。
而希望放在自己规划的目录下。 这时就可以操作系统的 PYTHONPATH 环境变量,该环境变量包含一系列的目录。
该环境变量下的所有目录都能被python解释器搜到。
这样我们就可以将代码放到PYTHONPATH 环境变量包含的目录下(注意不能是子目录,除非是包),就可以被别的程序import了。
设置PYTHONPATH 环境变量是相对比较好的方式,推荐使用。
案例三:路径的优先级
根据上面的介绍,一个模块要能别的程序引用(import)到,可以和程序放在一个目录,可以放到python系统目录下,可以放到PYTHONPATH 环境变量包含的目录下,那哪个优先级最高。
这时我们可以测试下,写三个同名文件,文件中定义同名的函数,函数只有一个print语句,但三个文件中的函数的print语句内容不同。
再编写另外一个程序import上面这个文件,并调用定义的函数,看看输出,就知道优先级了。
经过测试,发现优先级从高到底分别是:
1)当前目录
2)环境变量PYTHONPATH包含的路径
3)python系统目录
这个其实也很好理解,正常情况,越是用户的设置优先级越高。
案例四:包
我们上面的介绍,每个模块都是独立的一个python文件。为了让python能发现他们,必须放在相应的目录下。
没有分层,容易造成命名冲突和管理上的混乱。
特别在实际情况下,一个功能往往由多个模块(文件)组成,一般我们希望把这些代码放在一个目录下,便于管理。
这就要用到python的包的机制了。
python的包,物理上是一个目录,它实际上也是一个模块,只是比较特殊的模块,就是它还能包含其它模块。
下面我们举例来说明:
我们创建一个目录,如 testpackage
要想这个目录成为一个python包,而不是一个普通的目录,关键是在该目录下创建一个文件 __init__.py , init的前后分别是两个连续的下划线。
__init__.py文件名是固定的,但其中内容是任意的,就如同编写一个模块一样,可以放置任意的代码。如:
#coding=utf-8
print "hello,i am package"
def hello():
print "good"
我们再在testpackage目录 所在的目录下建立一个test.py文件,内容如下
#coding=utf-8
import testpackage
testpackage.hello()
test.py中就导入了testpackage,这时我们执行test.py,发现输出:
hello,i am package
good
可以看出,testpackage就是一个特殊的模块,但因为它本身不是一个python文件,而是一个目录,那么它下面的__init__.py 就是模块的内容,导入包,其实就是导入__init__.py文件。 而普通模块对应的是python文件,要求模块名和文件名一致。
我们再在 testpackage 下建立两个文件,module1.py , module2.py ,内容分别是:
#coding=utf-8
def fun1():
print "module1"
#coding=utf-8
def fun2():
print "module2"
下面我们来使用这两个模块,修改test.py文件。修改后的test.py的内容如下:
#coding=utf-8
import testpackage
import testpackage.module1
from testpackage import module2
testpackage.hello()
testpackage.module1.fun1()
module2.fun2()
执行test.py的输出如下:
hello,i am package
good
module1
module2
下面我们来分析下test.py中的内容
可以看出,我们用两种不同的方式导入了module1模块和 module2模块。
采用import testpackage.module1 方式,则要求在使用module1中的函数等时,需要全路径引用,如testpackage.module1.fun1()。
采用from testpackage import module2方式,则要求在使用module2中的函数等时,可以省略包名引用,如module2.fun2()。
一般情况下,我们采用from导入的方式。
还有一点需要说明的是,导入包中的模块,这时就不再需要导入包,因为会自动先导入模块所在的包,也就是说会自动导入包的__init__.py文件。
另外一点,既然包是一个特殊的模块,它的存放和普通模块一样,可以和用它的程序在一个目录下,可以在python系统目录下,也可以放到环境变量PYTHONPATH包含的目录下。
有了包这个功能,对于复杂的程序,就可以更好的组织源代码。
案例五:模块中能放什么呢?
在前面的例子中,已经涉及到了一些内容,下面我们再来更为详细的介绍下模块中能放什么,怎么用的问题。
第一,模块中能放什么,理论上说,跟普通的python代码文件一样,可以放 变量、函数定义、类定义,甚至直接的语句调用等内容。
第二,用的问题。首先就要被导入。
被导入时,模块中直接写的语句,如 print就会被立即执行,变量等也会被定义和初始化(如果有的话)。
第三,一个python文件,既可以作为作为主程序直接被执行,也可以作为一个模块被其它程序(或模块)导入。
那有的时候,我们希望有些直接写在文件最顶层的代码(不是函数或类)在作为程序直接执行 和 作为模块导入时是有差别的,那该怎么办?
我们还是看例子。
假设有 test1.py文件,其内容:
if __name__=="__main__":
print "hello,i am run self"
else:
print "hello,i am import by other"
如果我们执行运行test1.py,如在命令行下执行: python test1.py,我们发现打印的是 hello,i am run self 。
如果我们在别的程序中导入test1.py,如 import test1。我们发现打印的是 hello,i am import by other。
__name__是一个系统变量,当其值是__main__时,表示它是作为主程序被执行的。
通过这种方式,我们就可以将一个py文件 作为主程序 和 模块导入时 的差异化同时实现。
Python 2.7 学习笔记 模块和包的更多相关文章
- python学习笔记-模块和包
模块导入方法 1.import 语句 import module1[,module2[,...moduleN]] 当我们使用import语句的时候,Python解释器是怎么找到对应对文件对呢?答案是解 ...
- node 学习笔记 模块和包的管理与使用
1.前言 对于各种编程语言,代码组织是很重要的.而模块是node中的代码组织机制,node中的很多功能都以模块划分,而模块中又封装了许多方法,而且不会改变全局作用域,极大的方便了各开发者的需求. 2. ...
- python网络爬虫学习笔记
python网络爬虫学习笔记 By 钟桓 9月 4 2014 更新日期:9月 4 2014 文章文件夹 1. 介绍: 2. 从简单语句中開始: 3. 传送数据给server 4. HTTP头-描写叙述 ...
- Python Built-in Function 学习笔记
Python Built-in Function 学习笔记 1. 匿名函数 1.1 什么是匿名函数 python允许使用lambda来创建一个匿名函数,匿名是因为他不需要以标准的方式来声明,比如def ...
- Requests:Python HTTP Module学习笔记(一)(转)
Requests:Python HTTP Module学习笔记(一) 在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用并且功能强大,完全可以代替python的标 ...
- [转帖]Linux学习笔记之rpm包管理功能全解
Linux学习笔记之rpm包管理功能全解 https://www.cnblogs.com/JetpropelledSnake/p/11177277.html rpm 的管理命令 之前学习过 yum 的 ...
- python数据分析入门学习笔记
学习利用python进行数据分析的笔记&下星期二内部交流会要讲的内容,一并分享给大家.博主粗心大意,有什么不对的地方欢迎指正~还有许多尚待完善的地方,待我一边学习一边完善~ 前言:各种和数据分 ...
- python数据分析入门学习笔记儿
学习利用python进行数据分析的笔记儿&下星期二内部交流会要讲的内容,一并分享给大家.博主粗心大意,有什么不对的地方欢迎指正~还有许多尚待完善的地方,待我一边学习一边完善~ 前言:各种和数据 ...
- Python基础班学习笔记
本博客采用思维导图式笔记,所有思维导图均为本人亲手所画.因为本人也是初次学习Python语言所以有些知识点可能不太全. 基础班第一天学习笔记:链接 基础班第二天学习笔记:链接 基础班第三天学习笔记:链 ...
随机推荐
- 1TB到底能存放多少东西?
网盘大战逐渐升级,360和百度网盘先后推出的1TB网盘存储,而腾讯甚至为其微云网盘打出10TB的招牌来哄抢用户. 这里我们聊聊1TB的网盘究竟能放多少东西? 以下是我在网上找到的一些资料. 一)30年 ...
- 基于SIM 卡卡基不同制作工艺的研究
1 国内外现行的SIM 卡卡基制作工艺 SIM 卡由卡基和芯片两部分组成.卡基上有植入芯片的台阶式芯片槽,SIM 卡的芯片通过多点焊接植入台阶式芯片槽之中与卡基组成SIM 卡,然后经过个性化数据处理, ...
- php命名空间及和autoload结合使用问题。
在讨论如何使用命名空间之前,必须了解 PHP 是如何知道要使用哪一个命名空间中的元素的.可以将 PHP 命名空间与文件系统作一个简单的类比.在文件系统中访问一个文件有三种方式: 相对文件名形式如foo ...
- vs2013 linq to mysql
安装文件 1.下载安装文件 2.创建项目 3.创建mysql数据连接 4.新建ADO.NET数据模型 项目实现代码 using (WorkerContainer db = new WorkerCont ...
- golang实现udp接入服务器
前端通过udp与接入服务器连接,接入服务器与后端tcp服务器维持tcp连接.目录结构及后端tcp服务器代码同上一篇博客. main.go package main import ( "lot ...
- JavaScript 覆盖document.createElement 方法 解决window.close在火狐下不兼容问题)
近期项目遇到了问题,有个asp.net web程序仅仅能在IE7 执行.如今xp都淘汰了,大家都用IE8-IE11,因此这个web app也须要升级 适应全部IE版本号.照成IE版本号不兼容的问题主要 ...
- HDU 4716 A Computer Graphics Problem
A Computer Graphics Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- 关于移动端 rem 布局的一些总结
[资源一]基础知识恕不回顾 基础知识参考以下两篇博客: http://isux.tencent.com/web-app-rem.html http://www.w3cplus.com/css3/def ...
- 使用RadioGroup与RadioButton实现多选一
RadioGroup是RadioButton的集合, RadioGroup里面可以包含很多RadioButton,提供多选一机制,只能选择其中一个 RadioGroup的orientation(方向) ...
- BZOJ 1618: [Usaco2008 Nov]Buying Hay 购买干草( dp )
无限背包dp.. 因为题目中说至少到 H 磅 , 我就直接把 H * 2 了.. ----------------------------------------------------------- ...