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 转换成 字符串时间
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 时间替换
datetime模块

 

 

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文件

 

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文件

自己创建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文档
python创建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命令就能有效的完成我们需要的操作。

      subprocess模块允许一个进程创建一个新的子进程,通过管道连接到子进程的stdin/stdout/stderr,获取子进程的返回值等操作。

 

这个模块一个类: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。
Popen方法

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

需要交互的命令示例

待续

 

posted @ 2017-06-14 18:06  wanstack  阅读(179)  评论(0)    收藏  举报