一、模块&包

模块(modue)的概念:

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。

为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。

使用模块有什么好处?

最大的好处是大大提高了代码的可维护性。

其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。

所以,模块一共三种:

python标准库第三方模块应用程序自定义模块

另外,使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。

模块导入方法

1. import 语句

import module1[, module2[,... moduleN]

当我们使用import语句的时候,Python解释器是怎样找到对应的文件的呢?答案就是解释器有自己的搜索路径,存在sys.path里。

['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu','/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages'] 

2. from…import 语句

from modname import name1[, name2[, ... nameN]]

这个声明不会把整个modulename模块导入到当前的命名空间中,只会将它里面的name1或name2单个引入到执行这个声明的模块的全局符号表。

运行本质

#1 import test#2 from test import add  

无论1还是2,首先通过sys.path找到test.py,然后执行test脚本(全部执行),区别是1会将test这个变量名加载到名字空间,而2只会将add这个变量名加载进来。  

包(package)

如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。

请注意,每一个包目录下面都会有一个init.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录(文件夹),而不是一个包。init.py可以是空文件,也可以有Python代码,因为init.py本身就是一个模块,而它的模块名就是对应包的名字。

如果我们是直接执行某个.py文件的时候,该文件中那么”name == 'main'“是True,但是我们如果从另外一个.py文件通过import导入该文件的时候,这时name的值就是我们这个py文件的名字而不是main。

这个功能还有一个用处:调试代码的时候,在”if name == 'main'“中加入一些我们的调试代码,我们可以让外部模块调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

二、time模块

三种时间表示

时间戳(timestamp) : 通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。格式化的时间字符串元组(struct_time) : struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)

import time# 1 time() :返回当前时间的时间戳time.time() #1473525444.037215# 2 localtime([secs])# 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。time.localtime() #time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0,# tm_min=38, tm_sec=39, tm_wday=6, tm_yday=255, tm_isdst=0)time.localtime(1473525444.037215)# 3gmtime([secs]) 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。# 4 mktime(t) : 将一个struct_time转化为时间戳。print(time.mktime(time.localtime()))#1473525749.0# 5 asctime([t]) : 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。# 如果没有参数,将会将time.localtime()作为参数传入。print(time.asctime())#Sun Sep 11 00:43:43 2016#----------------------------------------------------------# 6 ctime([secs]) : 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为# None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。print(time.ctime()) # Sun Sep 11 00:46:38 2016print(time.ctime(time.time())) # Sun Sep 11 00:46:38 2016# 7 strftime(format[, t]) : 把一个代表时间的元组或者struct_time(如由time.localtime()和# time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个# 元素越界,ValueError的错误将会被抛出。print(time.strftime("%Y-%m-%d %X", time.localtime()))#2016-09-11 00:49:56# 8 time.strptime(string[, format])# 把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))#time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6,# tm_wday=3, tm_yday=125, tm_isdst=-1)#在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。# 9 sleep(secs)# 线程推迟指定的时间运行,单位为秒。# 10 clock()# 这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。# 而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行# 时间,即两次时间差。

三、random模块

import randomprint(random.random()) #产生一个0到3的随机浮点数,print(random.uniform(1,100)) #产生一个自定义范围的浮点数print(random.randint(0,5)) #产生一个指定范围的随机整数,包括5print(random.randrange(0,5)) #产生一个指定范围的随机整数,不包括5print(random.choice([1,23,33])) #在给定的列表内随机选取一个数字print(random.sample([1,2,3,4],2)) #在给定的列表表随机选取2个数字l=[1,2,3,4,5]random.shuffle(l) #打乱列表里元素的位置顺序print(l)#----生成随机码函数----def code_v(x): #x表示要生成多少位的随机数 code_str='' for i in range(10): code_int=random.randint(0,9) #生成数字 code_alp_A=chr(random.randint(65,90)) #生成大写字母 code_alp_a=chr(random.randint(97,122)) #生成小写字母 code_alp=random.choice([code_alp_A,code_alp_a]) #从大小写字母 随机选取一个 code_res=str(random.choice([code_int,code_alp])) #从数字和最终的字母随机选取一个 code_str += code_res #拼接字符串 return code_strprint(code_v(5))四、os模块

os模块是与操作系统交互的一个接口

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cdos.curdir 返回当前目录: ('.')os.pardir 获取当前目录的父目录字符串名:('..')os.makedirs('dirname1/dirname2') 可生成多层递归目录os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirnameos.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirnameos.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印os.remove() 删除一个文件os.rename("oldname","newname") 重命名文件/目录os.stat('path/filename') 获取文件/目录信息os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'os.system("bash command") 运行shell命令,直接显示os.environ 获取系统环境变量os.path.abspath(path) 返回path规范化的绝对路径os.path.split(path) 将path分割成目录和文件名二元组返回os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素os.path.exists(path) 如果path存在,返回True;如果path不存在,返回Falseos.path.isabs(path) 如果path是绝对路径,返回Trueos.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回Falseos.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回Falseos.path.join(path2[, path3[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

如何让程序自动导入path路径

import sys,ose=os.path.abspath(__file__) #获取当前执行脚本的绝对路径f=os.path.dirname(e) # 获取脚本执行的目录l=os.path.dirname(f) #获取脚本执行的上级目录。也就是获取到模块目录的父母录print(l)sys.path.append(l) 导入目录from my_module import calcal.lxd() 执行自定义目录模块、验证五、sys模块

sys.argv

import sysprint(sys.argv)command=sys.argv[1] #获取脚本执行时第一个参数 postpath=sys.argv[2] #获取脚本执行时,第二个参数 lingxd执行脚本时,传入参数python 1.py post lingxd

sys.exit(n) 退出程序,正常退出时exit(0)sys.version 获取Python解释程序的版本信息sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值sys.platform 返回操作系统平台名称

进度条

import sys,timefor i in range(100): sys.stdout.write('#') #这一步相当于print time.sleep(0.1) sys.stdout.flush() #刷新六、json &pickle模块

eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。

序列化

我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

json

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

import jsondic={'name':'alex'}f = open('hello','w')dic_str=json.dumps(dic) f.write(dic_str)f_read=open('hello')data=json.loads(f_read.read())print(data,type(data))

import json#dct="{'1':111}"#json 不认单引号#dct=str({"1":111})#报错,因为生成的数据还是单引号:{'one': 1}dct='{"1":"111"}'print(json.loads(dct))#conclusion:# 无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads

pickle

Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

import pickledic={'name':'alvin','age':23,'sex':'male'}print(type(dic))#<class 'dict'>j=pickle.dumps(dic)print(type(j))#<class 'bytes'>f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'f.write(j) #-------------------等价于pickle.dump(dic,f)f.close()#-------------------------反序列化import picklef=open('序列化对象_pickle','rb')data=pickle.loads(f.read())# 等价于data=pickle.load(f)print(data['age']) 七、shelve模块

shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型

import shelvef = 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'])八、xml模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单

xml的格式如下,就是通过<>节点来区别数据结构的:

<?xml version="1.0"?><data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country></data>

xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:

import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml")root = tree.getroot()print(root.tag)#遍历xml文档for child in root: print(child.tag, child.attrib) for i in child: print(i.tag,i.text)#只遍历year 节点for node in root.iter('year'): print(node.tag,node.text)#---------------------------------------import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml")root = tree.getroot()#修改for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) node.set("updated","yes")tree.write("xmltest.xml")#删除nodefor country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country)tree.write('output.xml')

自己创建xml文档:

import xml.etree.ElementTree as ETnew_xml = ET.Element("namelist")name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})age = ET.SubElement(name,"age",attrib={"checked":"no"})sex = ET.SubElement(name,"sex")sex.text = '33'name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})age = ET.SubElement(name2,"age")age.text = '19'et = ET.ElementTree(new_xml) #生成文档对象et.write("test.xml", encoding="utf-8",xml_declaration=True)ET.dump(new_xml) #打印生成的格式创建xml文档九、re模块

正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

*元字符之 . ^ $ + ? { }**

import reret=re.findall('a..in','helloalvin') # . 表示任意字符print(ret)#['alvin']ret=re.findall('^a...n','alvinhelloawwwn') # ^表示以什么开头print(ret)#['alvin']ret=re.findall('a...n$','alvinhelloawwwn') # $ 表示已什么结尾print(ret)#['awwwn']ret=re.findall('abc*','abcccc')#贪婪匹配[0,+oo] 重复任意次数,包括0次print(ret)#['abcccc']ret=re.findall('abc+','abccc')#[1,+oo] 至少匹配一次print(ret)#['abccc']ret=re.findall('abc?','abccc')#[0,1] 最多匹配一次print(ret)#['abc']ret=re.findall('abc{1,4}','abccc') 匹配1到4次print(ret)#['abccc'] 贪婪匹配

注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

ret=re.findall('abc*?','abcccccc')print(ret)#['ab']

元字符之字符集[]:

ret=re.findall('a[bc]d','acd') #[]这里面的元素表示或print(ret)#['acd']ret=re.findall('[a-z]','acd')print(ret)#['a', 'c', 'd']ret=re.findall('[.*+]','a.cd+') #【】中括号内的元素 没有其他附加意思print(ret)#['.', '+']#在字符集里有功能的符号: - ^ \ret=re.findall('[1-9]','45dha3')print(ret)#['4', '5', '3']ret=re.findall('[^ab]','45bdha3') # 【^】表示取反print(ret)#['4', '5', 'd', 'h', '3']ret=re.findall('[\d]','45bdha3') # \表示转义,附加其功能print(ret)#['4', '5', '3']

元字符之转义符\

反斜杠后边跟元字符去除特殊功能,比如\.反斜杠后边跟普通字符实现特殊功能,比如\d\d 匹配任何十进制数;它相当于类 [0-9]。\D 匹配任何非数字字符;它相当于类 [^0-9]。\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]\b 匹配一个特殊字符边界,比如空格 ,&,#等ret=re.findall('I\b','I am LIST')print(ret)#[]ret=re.findall('I\\b','I am LIST') print(ret)#[I]ret=re.findall(r'I\b','I am LIST')print(ret)#['I']import reret=re.findall('c\l','abc\le')print(ret)#[]ret=re.findall('c\\l','abc\le')print(ret)#[]ret=re.findall('c\\\\l','abc\le')print(ret)#['c\\l']ret=re.findall(r'c\\l','abc\le')print(ret)#['c\\l']#-----------------------------eg2:#之所以选择\b是因为\b在ASCII表中是有意义的m = re.findall('\bblow', 'blow')print(m)m = re.findall(r'\bblow', 'blow')print(m)