Python基础(七)模块1
本节介绍一些python模块的简单使用
一、自定义模块
模块,用一砣代码实现了某个功能的代码集合。
类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。
如:os 是系统相关的模块;file是文件操作相关的模块
模块分为三种:
- 自定义模块
- 内置模块
- 开源模块
1、定义模块
情景一:

情景二:

情景三:

2、导入模块
Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入。导入模块有一下几种方法:
1 import module 2 from module.xx.xx import xx 3 from module.xx.xx import xx as rename 4 from module.xx.xx import *
导入模块其实就是告诉Python解释器去解释那个py文件
- 导入一个py文件,解释器解释该py文件
- 导入一个包,解释器解释该包下的 __init__.py 文件
那么问题来了,导入模块时可以导入位于哪些目录下的模块呢? 我们可以使用sys.path进行查看可以导入位于那些目录下的模块。
1 import sys 2 print sys.path
如果sys.path路径列表没有你想要的路径,可以通过 sys.path.append('路径') 添加。
通过os模块可以获取各种目录,例如:
1 import sys 2 import os 3 4 pre_path = os.path.abspath('../') 5 sys.path.append(pre_path)
二、开源模块
1、下载安装
下载安装有两种方式:
yum
pip
apt-get
下载源码
解压源码
进入目录
编译源码 python setup.py build
安装源码 python setup.py install
注:在使用源码安装时,需要使用到gcc编译和python开发环境,所以,需要先执行:
1 yum install gcc 2 yum install python-devel 3 或 4 apt-get python-dev
安装成功后,模块会自动安装到 sys.path 中的某个目录中,如:
1 /usr/lib/python2.7/site-packages/
三、模块使用
1、time & datetime模块
1 # author:wanstack 2 """ 3 时间相关的操作,时间有三种表示方式: 4 5 时间戳 1970年1月1日之后的秒,即:time.time() 6 格式化的字符串 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d') 7 结构化时间 元组包含了:年、日、星期等... time.struct_time 即:time.localtime() 8 """ 9 import time 10 # print(help(time)) 11 print(time.time()) # 1497337171.3823068 返回当前系统时间戳,从1970年1月1日0时0分0秒开始到现在的秒数 12 print(time.localtime()) # time.struct_time(tm_year=2017, tm_mon=6, tm_mday=13, tm_hour=15, tm_min=26, tm_sec=49, tm_wday=1, tm_yday=164, tm_isdst=0) 13 # 结构化时间 显示系统当前的时间,将时间戳转换为结构化时间 14 print(time.localtime(time.time())) # time.struct_time(tm_year=2017, tm_mon=6, tm_mday=13, tm_hour=15, tm_min=31, tm_sec=2, tm_wday=1, tm_yday=164, tm_isdst=0) 15 print(time.ctime()) # Tue Jun 13 15:06:52 2017 输出当前系统时间 16 print(time.ctime(1234567890)) # Sat Feb 14 07:31:30 2009 将 时间戳 转换成 可读时间 17 print(time.gmtime()) # time.struct_time(tm_year=2017, tm_mon=6, tm_mday=13, tm_hour=7, tm_min=26, tm_sec=8, tm_wday=1, tm_yday=164, tm_isdst=0) struct_time 使用的是UTC时间。我们默认使用的是北京时间, 北京时间= UTC +8小时 18 a = time.strptime('2017-06-13 15:58:14','%Y-%m-%d %H:%M:%S') # 将字符串格式转换成struct_time格式 19 print(a.tm_mday) # 获取结构化时间中的天数 20 print(a.tm_year) # 获取结构化时间中的年数 2017 21 22 # 将日期字符串 转成 时间戳 23 24 # 将字符串 转换成 struct_time时间格式 自定义时间格式 25 print(time.strptime('2017-06-13 15:58:14','%Y-%m-%d %H:%M:%S')) #time.struct_time(tm_year=2017, tm_mon=6, tm_mday=13, tm_hour=15, tm_min=58, tm_sec=14, tm_wday=1, tm_yday=164, tm_isdst=-1) 26 # 将struct_time格式 转换成 时间戳 27 print(time.mktime(time.localtime())) # 1497339155.0 将struct_time 转换为 时间戳 28 29 30 # 将 时间戳 转成 字符串格式 31 32 33 print(time.localtime(time.time())) # 将时间戳 转换成 struct_time格式时间 34 print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) # 2017-06-14 13:43:24 将struct_time 转换成 字符串时间

1 import datetime 2 import time 3 4 # print(help(datetime)) 5 print(datetime.datetime.now()) # 2017-06-13 16:08:30.463789 输出当前系统时间 6 print(datetime.date.today()) # 2017-06-13 # 输出当前系统日期 7 print(datetime.date.fromtimestamp(time.time()) ) # 2017-06-14 时间戳直接转成日期格式 8 print(datetime.datetime.now() + datetime.timedelta(days=3)) # 2017-06-17 13:55:07.750534 当前时间+3天 9 print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 2017-06-11 13:55:35.612528 当前时间-3天 10 print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 22017-06-14 16:56:12.757520 当前时间+3小时 11 print(datetime.datetime.now() + datetime.timedelta(hours=-3)) # 2017-06-14 10:56:12.757520 当前时间-3小时 12 13 c_time = datetime.datetime.now() 14 print(c_time.replace(minute=3,hour=2)) # 2017-06-14 02:03:22.719764 时间替换
2、random模块
1 # author:wanstack 2 import random 3 4 print(random.random()) # 0.822387499496826 用于生成一个0到1的随机符点数: 0 <= n < 1.0 5 print(random.randint(1,4)) # 用于生成一个指定范围内的整数 6 print(random.randrange(1,10)) # 从1到10的范围内取一个随机整数 7 print(random.uniform(1,10)) # 从1到10的范围内取一个随机浮点数 8 print(random.choice([1,2,3,4,[1,2,],'abc'])) # 从序列中获取一个随机元素 9 10 a = [1,2,3,4] # tuple不支持,set不支持,str不支持 11 random.shuffle(a) # 用于将一个列表中的元素打乱 12 print(a) 13 b = random.sample(a,2) # 从列表a中随机获取2个元素作为返回值 14 print(b) 15 16 17 # 随机验证码,5位数的随机验证码,大小写字母数字混杂 18 19 def verification_code(): 20 code='' 21 num_code = random.choice(range(10)) 22 supper_alpha_code = chr((random.choice(range(65,90)))) 23 lower_alpha_code = chr((random.choice(range(97,122)))) 24 for i in range(5): 25 # 从序列中获取一个随机元素 26 choice = random.choice([num_code,supper_alpha_code,lower_alpha_code]) 27 choice = str(choice) 28 code = code + choice 29 print(code) 30 31 32 verification_code()
3、json&pickle
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 import json 2 x="[null,true,false,1]" 3 print(eval(x)) 4 print(json.loads(x))
什么是序列化?
我们把 对象(变量)从内存中 变成 可存储或传输 的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

一些高级对象比如函数对象,类对象等是不能被json.dumps序列化的。只能使用pickle.dumps
1 # author:wanstack 2 3 import json 4 5 #------------- dumps/loads 6 dic = {'name':'wanstack','age':29} 7 8 data = json.dumps(dic) # 把字典对象序列化 9 f = open('JSON_test','a') 10 f.write(data) 11 f.close() 12 13 f=open('JSON_test','r') 14 data = f.read() 15 data = json.loads(data) # 从磁盘中反序列化成字典格式 16 print(data) # {'name': 'wanstack', 'age': 29} 17 f.close() 18 #------------ dump/load 19 dic = {'name':'wanstack','age':29} 20 f = open('JSON_test','a') 21 json.dump(dic,f) 22 f.close() 23 24 f=open('JSON_test','r') 25 data= json.load(f) 26 print(data) # {'name': 'wanstack', 'age': 29} 27 f.close()
其他例子:
1 #----------------------------序列化 2 import json 3 4 dic={'name':'alvin','age':23,'sex':'male'} 5 print(type(dic))#<class 'dict'> 6 7 j=json.dumps(dic) 8 print(type(j))#<class 'str'> 9 10 11 f=open('序列化对象','w') 12 f.write(j) #-------------------等价于json.dump(dic,f) 13 f.close() 14 #-----------------------------反序列化<br> 15 import json 16 f=open('序列化对象') 17 data=json.loads(f.read())# 等价于data=json.load(f)
注意点:
1 import json 2 #dct="{'1':111}"#json 不认单引号 3 #dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1} 4 5 dct='{"1":"111"}' 6 print(json.loads(dct)) 7 8 #conclusion: 9 # 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads 10 11 注意点
pickle和json使用一致:
1 ##----------------------------序列化 2 import pickle 3 4 dic={'name':'alvin','age':23,'sex':'male'} 5 6 print(type(dic))#<class 'dict'> 7 8 j=pickle.dumps(dic) 9 print(type(j))#<class 'bytes'> 10 11 12 f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes' 13 f.write(j) #-------------------等价于pickle.dump(dic,f) 14 15 f.close() 16 #-------------------------反序列化 17 import pickle 18 f=open('序列化对象_pickle','rb') 19 20 data=pickle.loads(f.read())# 等价于data=pickle.load(f) 21 22 23 print(data['age'])
Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
4、shelve模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve f = shelve.open(r'shelve.txt') # f['stu1_info']={'name':'alex','age':'18'} # f['stu2_info']={'name':'alvin','age':'20'} # f['school_info']={'website':'oldboyedu.com','city':'beijing'} # # # f.close() print(f.get('stu_info')['age'])
5、xml模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
1 <?xml version="1.0"?> 2 <data> 3 <country name="Liechtenstein"> 4 <rank updated="yes">2</rank> 5 <year>2008</year> 6 <gdppc>141100</gdppc> 7 <neighbor name="Austria" direction="E"/> 8 <neighbor name="Switzerland" direction="W"/> 9 </country> 10 <country name="Singapore"> 11 <rank updated="yes">5</rank> 12 <year>2011</year> 13 <gdppc>59900</gdppc> 14 <neighbor name="Malaysia" direction="N"/> 15 </country> 16 <country name="Panama"> 17 <rank updated="yes">69</rank> 18 <year>2011</year> 19 <gdppc>13600</gdppc> 20 <neighbor name="Costa Rica" direction="W"/> 21 <neighbor name="Colombia" direction="E"/> 22 </country> 23 </data> 24 25 xml数据
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
1 import xml.etree.ElementTree as ET 2 3 tree = ET.parse("xmltest.xml") 4 root = tree.getroot() 5 print(root.tag) 6 7 #遍历xml文档 8 for child in root: 9 print(child.tag, child.attrib) 10 for i in child: 11 print(i.tag,i.text) 12 13 #只遍历year 节点 14 for node in root.iter('year'): 15 print(node.tag,node.text) 16 #--------------------------------------- 17 18 import xml.etree.ElementTree as ET 19 20 tree = ET.parse("xmltest.xml") 21 root = tree.getroot() 22 23 #修改 24 for node in root.iter('year'): 25 new_year = int(node.text) + 1 26 node.text = str(new_year) 27 node.set("updated","yes") 28 29 tree.write("xmltest.xml") 30 31 32 #删除node 33 for country in root.findall('country'): 34 rank = int(country.find('rank').text) 35 if rank > 50: 36 root.remove(country) 37 38 tree.write('output.xml')
自己创建xml文档:
1 import xml.etree.ElementTree as ET 2 3 4 new_xml = ET.Element("namelist") 5 name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) 6 age = ET.SubElement(name,"age",attrib={"checked":"no"}) 7 sex = ET.SubElement(name,"sex") 8 sex.text = '33' 9 name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) 10 age = ET.SubElement(name2,"age") 11 age.text = '19' 12 13 et = ET.ElementTree(new_xml) #生成文档对象 14 et.write("test.xml", encoding="utf-8",xml_declaration=True) 15 16 ET.dump(new_xml) #打印生成的格式 17 18 创建xml文档
6、subprocess模块
常见用法:
import subprocess
def cpu_top5():
shell_cmd = 'ps -e -o "%u:%C:%p:%z:%a"| grep -v COMMAND | sort -k1 -nr | head -5'
p = subprocess.Popen(shell_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result = p.stdout.readlines()
return result
当我们需要调用系统的命令的时候,最先考虑的os模块。用os.system()和os.popen()来进行操作。但是这两个命令过于简单,不能完成一些复杂的操作,如给运行的命令提供输入或者读取命令的输出,判断该命令的运行状态,管理多个命令的并行等等。这时subprocess中的Popen命令就能有效的完成我们需要的操作。
这个模块一个类:Popen。
#Popen它的构造函数如下: subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None,stderr=None, preexec_fn=None, close_fds=False, shell=False,<br> cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
# 参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。 # 如果是序列类型,第一个元素通常是可执行文件的路径。我们也可以显式的使用executeable参 # 数来指定可执行文件的路径。在windows操作系统上,Popen通过调用CreateProcess()来创 # 建子进程,CreateProcess接收一个字符串参数,如果args是序列类型,系统将会通过 # list2cmdline()函数将序列类型转换为字符串。 # # # 参数bufsize:指定缓冲。我到现在还不清楚这个参数的具体含义,望各个大牛指点。 # # 参数executable用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如 # 果将参数shell设为True,executable将指定程序使用的shell。在windows平台下,默认的 # shell由COMSPEC环境变量来指定。 # # 参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE, # 文件描述符或文件对象,也可以设置为None,表示从父进程继承。 # # 参数preexec_fn只在Unix平台下有效,用于指定一个可执行对象(callable object),它将 # 在子进程运行之前被调用。 # # 参数Close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会 # 继承父进程的输入、输出、错误管道。我们不能将close_fds设置为True同时重定向子进程的标准 # 输入、输出与错误(stdin, stdout, stderr)。 # # 如果参数shell设为true,程序将通过shell来执行。 # # 参数cwd用于设置子进程的当前目录。 # # 参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父 # 进程中继承。 # # 参数Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下 # 用’/r/n’表示换,而Linux下用’/n’。如果将此参数设置为True,Python统一把这些换行符当 # 作’/n’来处理。 # # 参数startupinfo与createionflags只在windows下用效,它们将被传递给底层的 # CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。 parameter
简单命令:
import subprocess a=subprocess.Popen('ls')# 创建一个新的进程,与主进程不同步 print('>>>>>>>',a)#a是Popen的一个实例对象 ''' >>>>>>> <subprocess.Popen object at 0x10185f860> __init__.py __pycache__ log.py main.py ''' # subprocess.Popen('ls -l',shell=True) # subprocess.Popen(['ls','-l'])
subprocess.PIPE
在创建Popen对象时,subprocess.PIPE可以初始化stdin, stdout或stderr参数。表示与子进程通信的标准流。
import subprocess # subprocess.Popen('ls') p=subprocess.Popen('ls',stdout=subprocess.PIPE)#结果跑哪去啦? print(p.stdout.read())#这这呢:b'__pycache__\nhello.py\nok.py\nweb\n'
这是因为subprocess创建了子进程,结果本在子进程中,if 想要执行结果转到主进程中,就得需要一个管道,即 : stdout=subprocess.PIPE
subprocess.STDOUT
创建Popen对象时,用于初始化stderr参数,表示将错误通过标准输出流输出。
Popen的方法
Popen.poll() 用于检查子进程是否已经结束。设置并返回returncode属性。 Popen.wait() 等待子进程结束。设置并返回returncode属性。 Popen.communicate(input=None) 与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。 Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如 果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。 Popen.send_signal(signal) 向子进程发送信号。 Popen.terminate() 停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。 Popen.kill() 杀死子进程。 Popen.stdin 如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。 Popen.stdout 如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。 Popen.stderr 如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。 Popen.pid 获取子进程的进程ID。 Popen.returncode 获取进程的返回值。如果进程还没有结束,返回None。
supprocess模块的工具函数
supprocess模块提供了一些函数,方便我们用于创建进程来实现一些简单的功能。 subprocess.call(*popenargs, **kwargs) 运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。如果子进程不需要进行交 互,就可以使用该函数来创建。 subprocess.check_call(*popenargs, **kwargs) 与subprocess.call(*popenargs, **kwargs)功能一样,只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常。在异常对象中,包 括进程的returncode信息。 check_output(*popenargs, **kwargs) 与call()方法类似,以byte string的方式返回子进程的输出,如果子进程的返回值不是0,它抛出CalledProcessError异常,这个异常中的returncode包含返回码,output属性包含已有的输出。 getstatusoutput(cmd)/getoutput(cmd) 这两个函数仅仅在Unix下可用,它们在shell中执行指定的命令cmd,前者返回(status, output),后者返回output。其中,这里的output包括子进程的stdout和stderr。
import subprocess #1 # subprocess.call('ls',shell=True) ''' hello.py ok.py web ''' # data=subprocess.call('ls',shell=True) # print(data) ''' hello.py ok.py web ''' #2 # subprocess.check_call('ls',shell=True) ''' hello.py ok.py web ''' # data=subprocess.check_call('ls',shell=True) # print(data) ''' hello.py ok.py web ''' # 两个函数区别:只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常 #3 # subprocess.check_output('ls')#无结果 # data=subprocess.check_output('ls') # print(data) #b'hello.py\nok.py\nweb\n' 演示
交互命令:
终端输入的命令分为两种:
- 输入即可得到输出,如:ifconfig
- 输入进行某环境,依赖再输入,如:python
需要交互的命令示例
待续
浙公网安备 33010602011771号