Python 常用模块

Python之路 Day5 常用模块

import 导入模块


1.定义

   类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),多个.py 文件组成的代码集合就称为模块,是为了实现某个功能的代码集合。 

2.导入模块

   导入模块其实就是告诉Python解释器去解释那个py文件,导入一个py文件,解释器解释该py文件。导入一个包,解释器解释该包下的 __init__.py 文件。
   
导入方法:   
import module
from module.xx.xx import xx
from module.xx.xx import xx as rename  
from module.xx.xx import *

3.模块的分类

  • 标准库
  • 开源模块
  • 自定义模块

时间模块


模块有time,datetime表示方式有(1)时间戳,(2)格式化时间字符串,(3)元组(struct_time)共九个元素。

时间戳

>>> time.time()
1550499641.1268253    #打印从19700101 8:00:00到当前时间所经历的秒数
>>> time.mktime(time.strptime("2018-11-08 15:32:02","%Y-%m-%d %X"))
1541662322.0          #将当前时间转为时间戳

格式化时间字符串

>>> time.ctime(time.time())
'Mon Feb 18 22:24:59 2019'               #接收的参数是字符串
>>> time.asctime(time.localtime())
'Mon Feb 18 22:25:02 2019'               #接收的参数是元组
>>> print(datetime.datetime.now())
2019-02-18 22:26:41.758610
>>> time.strftime('%X %Y-%m-%d',time.localtime()) 
'22:33:20 2019-02-18'                    #根据time.localtime()来自定义时间
>>> print(time.strptime("2018-11-08 15:32:02","%Y-%m-%d %X"))
time.struct_time(tm_year=2018, tm_mon=11, tm_mday=8, tm_hour=15, tm_min=32, tm_sec=2, tm_wday=3, tm_yday=312, tm_isdst=-1)     #将'2018-11-08 15:32:02'转为time.localtime()格式,#前后格式需要一一对应但是顺序不需要。

元组(struct_time)

>>> time.gmtime()       #UTC标准时间
time.struct_time(tm_year=2019, tm_mon=2, tm_mday=18, tm_hour=14, tm_min=30, tm_sec=32, tm_wday=0, tm_yday=49, tm_isdst=0)
>>> time.localtime()    #当前时间
time.struct_time(tm_year=2019, tm_mon=2, tm_mday=18, tm_hour=22, tm_min=30, tm_sec=36, tm_wday=0, tm_yday=49, tm_isdst=0)

获取过去或未来时间

>>> print(datetime.datetime.now() + datetime.timedelta(3))
2019-02-21 22:37:31.583559      #三天后时间
>>> print(datetime.datetime.now() + datetime.timedelta(hours=3))
2019-02-19 01:38:06.303301      #三小时后时间
>>> print(datetime.datetime.now() + datetime.timedelta(hours=-3))
2019-02-18 19:38:28.503632      #三小时前时间

替换时间

>>> print(datetime.datetime.now().replace(minute=3,hour=2))
2019-02-18 02:03:08.503691

random模块


import random
print(random.random())          ##生成0到一之间随机数
print(random.randint(100,999))  ##生成100到999之间随机数
print random.randrange(1,10)    ##生成1到10之间随机数,不包含10
print(random.choice([1,'23',[4,5]]))  #从列表中返回其中一个值 
print(random.uniform(1,3))      ##大于1小于3的小数,如1.927109612082716
print(random.sample('hello',3)) ##从总体序列或集合中选择多个唯一的随机元素,以列表形式返回。		

item=[1,3,5,7,9]
random.shuffle(item)            ##打乱item的顺序,相当于"洗牌"
print(item)

import string
print(string.ascii_lowercase)       ##生成小写字母
print(string.ascii_uppercase)       ##生成大写字母
print(string.ascii_letters)         ##生成所有字母
print(string.digits)                ##生成0-9数字

生成随机验证码:
import random,string
checkcode = ''
road=True
for i in range(8):
    if road:
        checkcode+=random.choice(string.ascii_letters)
        road=False
    else:
        checkcode += random.choice(string.digits)
        road=True
print(checkcode)

os模块


提供对操作系统进行调用的接口

import os
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"	
",Linux下为"
"
os.pathsep    输出用于分割文件路径的字符串
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示,结果无法赋值给变量
os.popen("bash command")   执行系统命令,可以赋值保存但是需要read读。
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不存在,返回False
os.path.isabs(path)  如果path是绝对路径,返回True
os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间

shutil模块


import shutil
shutil.copyfile('1.txt','2.txt')      拷贝文件
shutil.copy('1.txt','2.txt')          拷贝文件和权限     
shutil.copy2('1.txt','2.txt')         拷贝文件和权限,还有时间等属性。
shutil.copymode('f1.log', 'f2.log')   仅拷贝权限。内容、组、用户均不变,目标文件需要已经存在。
shutil.copystat('f1.log', 'f2.log')   仅拷贝权限和状态信息访问时间等。内容、组、用户均不变,目标文件需要已经存在。
shutil.move('1.txt','2.txt')          移动文件,相同目录下相当与改名
shutil.copytree(src, dst)             拷贝目录
shutil.rmtree(path)                   删除目录

压缩目录:
shutil.make_archive(base_name, format,...)
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径。
format:	   压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir:  要压缩的文件夹路径(默认当前目录)压缩文件。
注:默认会给你的压缩包加上后缀名。

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
import zipfile

#压缩
z=zipfile.ZipFile('test.zip','w')
z.write('test.xml')
z.write('test1.xml')
z.close()

#解压出一个文件
z=zipfile.ZipFile('test.zip','r')
z.extract(member='test.xml')
z.close()

#解压出所有文件
z=zipfile.ZipFile('test.zip','r')
z.extractall(member='test.xml')
z.close()

import tarfile

#压缩
tar = tarfile.open('your.tar','w')
tar.add('test.xml', arcname='test.xml')
tar.add('test1.xml', arcname='test1.xml')
tar.close()

# 解压
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可设置解压地址
tar.close()

shelve模块

shelve模块以k,v格式存储数据,可以持久化任何pickle可支持的Python数据类型。

#写入:
d=shelve.open('shelve_test')
info={'age':22,'j  ob':'it'}
name=['zyl','syf','test']
d['in']=info
d['na']=name
d.close()

#读取例
d=shelve.open('shelve_test')
print(d.get('in '))
结果:{'age': 22, 'j  ob': 'it'}

xml模块

import xml.etree.ElementTree as ET

#读取:
tree = ET.parse('xmltest.xml')
root=tree.getroot()                       
for i in root:
    print(i.tag,i.attrib)        ##tag是第一层的标签名,attrib是第一层标签名的信息。
    for c in i:                        
         print(c.tag,c.text,c.attrib)    ##打印第二层的标签名,文本数据,标签名的信息。

for node in root.iter('year'):
    print(node.tag,node.text)            ##只打印单个节点信息,就算year在多级目录下也会打印。

#修改:
tree = ET.parse('xmltest.xml')
root=tree.getroot()
for node in root.iter('year'):
    node.text=str(int(node.text)+1)          ##所有标签为year的内容加1
    node.set("updated",'yes')                ##设置标签属性。

tree.write('xmltest.xml')                    ##修改完毕后需要在写入到文件

删除某一段:
tree = ET.parse('xmltest.xml')
root=tree.getroot()
for country in root.findall('country'):
    rank=int(country.find('year').text)
    if rank == 2012:
         root.remove(country)                #删除年份为2012的节点
tree.write('output.xml')

编写xml文件:
new_xml=ET.Element('data')                                               #一级标签
info=ET.SubElement(new_xml,"personinfo",attrib={'enrolled':'yes'})       #二级标签
info2=ET.SubElement(new_xml,"personinfo2",attrib={'a':'666'})            #二级标签

name=ET.SubElement(info,"name")                                          #三级标签
age=ET.SubElement(info,'age')
name.text='zyl'                                                          #给三级标签设置值
age.text='30'               

name=ET.SubElement(info2,"name")                                         #三级标签
age=ET.SubElement(info2,'age')
name.text='wq'
age.text='16'


et=ET.ElementTree(new_xml)                                               #生成et对象
et.write('new_xml',encoding="utf-8",xml_declaration=True)                #写入到new_xml文件中

configparser模块

用于生成和修改常见配置文档
生成如下格式:

[Default]
a = 1
b = 2
c = 3
forwardx11 = yes

[bit]
user = hg

[topse]
port = 5022
forwardx11 = no

如果想用python生成一个这样的文档怎么做呢?

import configparser

#编写文件:
config=configparser.ConfigParser()
config["Default"]={'a':1,
            'b':2,
            'c':3}
config['bit']={}
config['bit']['user']='hg'

config['topse']={}
a=config['topse']
a['port']='5022'
a['forwardx11']='no'

config['Default']['ForwardX11']='yes'

with open('ConfParser.py','w') as configfile:
    config.write(configfile)

#返回节名称列表,不包括[DEFAULT]:
import configparser
config = configparser.ConfigParser()
config.read('example.ini')
config.sections()

#读取模块下单独的选项:
import configparser
config = configparser.ConfigParser()
config.read('example.ini')
config['bitbucket.org']['User']

#读取模块下选项和对应的参数:
>>>print(config.items('bit'))
[('user', 'hg')]

#只读取模块下所有的选项:
>>>config.options('bit')
['user']

#删除单个模块:
config.remove_section('group1')

#添加一个模块:
config.add_section('wupeiqi')

#给新加的模块添加一个键值对
config.set('wupeiqi','user','zyl')

#修改一个选项的值:
config.set('group2','k1',11111)     

#删除一个选项:
config.remove_option('group2','age')

#注意:所有修改文件的操作都需要冲新写入到一个文件中。
config.write(open('ConfParser.py','w'))

hashlib模块

用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512,MD5算法

import hashlib

#md5:
 m = hashlib.md5()
 m.update(b"Hello")         ##必须为bytes格式
 m.update(b"It's me")       ##多个值会组成一个值,相当于b“Hello It's me”
 print(m.digest())          #2进制格式hash
 print(m.hexdigest())       #16进制格式hash
 
#sha256:
 m = hashlib.sha512()
 m.update(b"Hello")
 print(m.hexdigest())
 
#加密中文格式:
 m = hashlib.sha512()
 m.update("小朱朱".encode(encoding='utf-8'))
 print(m.hexdigest()) 

re模块

常用正则表达式符号

'.'     默认匹配除
之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","
abc
eee",flags=re.MULTILINE)
'$'     匹配字符结尾,或e.search("foo$","bfoo
sdfsf",flags=re.MULTILINE).group()也可以
'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?'     匹配前一个字符1次或0次
'{m}'   匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
'[]'    匹配其中任意一个字符,也可以写为[a-zA-Z0-9]
'[^]'   排除其中所有字符


'A'    只从字符开头匹配,re.search("Aabc","alexabc") 是匹配不到的
''    匹配字符结尾,同$
'd'    匹配数字0-9
'D'    匹配非数字
'w'    匹配[A-Za-z0-9]
'W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、	、
、
 , re.search("s+","ab	c1
3").group() 结果 '	'

#flags标志位
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
例:re.search("([a-z]+)","aaaAaAC234aaa",flags=re.I)
S(DOTALL): 点任意匹配模式,改变'.'的行为,可以匹配到换行符。   
例:re.search(".+","aaaAaAC
234aaa",flags=re.S)

1.re.match函数

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
语法:re.match(pattern, string, flags=0)

#示例:
>>> import re
>>> obj = re.match('d+', '123uuasf')
>>> print(obj.group())
123

2.匹配对象方法

1.group()	  匹配的整个表达式的字符串
2.group(1)    第一个匹配的()中的值
3.groupdict() 返回以有别名的组的别名为键、以该组截获的子串为值的字典
  例:print(re.search("(?P<zyl>[0-9]{2})(?P<zz>d+)","1234567").groupdict())
  结果:{'zyl': '12', 'zz': '34567'}
4.start()	返回匹配开始的位置
5.end()	    返回匹配结束的位置
6.span()	返回一个元组包含匹配(开始,结束)的位置

3.re.search方法

扫描整个字符串并返回第一个成功的匹配。
#示例1:
>>> print(re.search('com','www.baidu.com').group())
com

#示例2:
>>> line = "Cats are smarter than dogs";
>>> searchobj=re.search(r'(.*re)(.*)(th.*)',line)   ##默认贪婪
>>> print(searchobj.group(2))
 smarter

4.re.sub方法

##替换字符串中的匹配项。
语法: re.sub(pattern, repl, string, count=0, flags=0)
#示例1:
>>> s='2017/19/31'
>>> print(re.sub('(d+)/(d+)/(d+)',r'3-2-1',s))
31-19-2017


#示例2:
>>> re.sub("[0-9]+",'|',"aaa234aa111sfaf")
'aaa|aa|sfaf'

pattern : 正则中的模式字符串。         
repl : 替换的字符串,也可为一个函数。    
string : 要被查找替换的原始字符串。     
count : 模式匹配后替换的最大次数,默认0表示替换所有的匹配。

5.findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表.match 和 search 是匹配一次而findall匹配所有。
#示例:
>>>print(re.findall('d+','zul111zyl111'))
['111', '111']

6.split方法

按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
语法:re.split(pattern, string[, maxsplit=0, flags=0])
#示例:
>>> re.split("[0-9]+","aaa234aa111sfaf")
['aaa', 'aa', 'sfaf']
>>> re.split("([0-9]+)","aaa234aa111sfaf")
['aaa', '234', 'aa', '111', 'sfaf']  #保留分隔符

每日练习

开发一个简单的python计算器

  1. 实现加减乘除及拓号优先级解析
  2. 用户输入1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致

代码如下

# Author:ZhuYuLiang
import re
def format_mark(express):
    express = express.replace('+-', '-')
    express = express.replace('-+', '-')
    express = express.replace('++', '+')
    express = express.replace('--', '+')
    express = express.replace('*+', '*')
    express = express.replace('+*', '*')
    express = express.replace('+/', '/')
    express = express.replace('/+', '/')
    return express

def Add_and_Sub(value):
    expr = value
    sub_expr = re.search(r"-?d+.?d*[+-]d+.?d*", expr)
    if not sub_expr:
        return expr
    else:
        sub_expr2 = sub_expr.group()
        if len(sub_expr2.split('+')) > 1:
            n1, n2 = sub_expr2.split('+')
            result = float(n1) + float(n2)
        else:
            n1, n2 = sub_expr2.split('-')
            result = float(n1) - float(n2)
        re_sub_expr = re.sub(r"-?d+.?d*[+-]d+.?d*", str(result), expr, count=1)
        bb = Add_and_Sub(str(re_sub_expr))
        return bb
def Multiplication_and_division(value):
    expr = value
    sub_expr = re.search(r"d+.?d*[/*]-?d+.?d*", expr)
    if not sub_expr:
        return expr
    else:
        sub_expr2 = sub_expr.group()
        if len(sub_expr2.split('/')) > 1:
            n1, n2 = sub_expr2.split('/')
            result = float(n1) / float(n2)
        elif len(sub_expr2.split('*')) > 1:
            n1, n2 = sub_expr2.split('*')
            result = float(n1) * float(n2)
        else:
            # 只计算乘除,加减直接pass,放入加减函数执行
            pass
        re_sub_expr = re.sub(r"d+.?d*[/*]-?d+.?d*", str(result), expr, count=1)
        # 反复调用除法
        bb = Multiplication_and_division(format_mark(re_sub_expr))
        return bb

def compute(value):
    value=Multiplication_and_division(format_mark(value))
    value=Add_and_Sub(format_mark(value))
    return value

def del_brackets(value):
    sub_expr=re.search('([^()]+)',value)
    if not sub_expr:
        return value
    else:
        sub_expr=sub_expr.group()[1:-1]
        sub_expr=compute(sub_expr)
        sub_expr3 = re.sub('(([+-*/.0-9]+))', str(sub_expr), value, count=1)
        delkuohao_expr=del_brackets(format_mark(sub_expr3))
        return delkuohao_expr

if __name__ == '__main__':
    while True:
        express=input('>>: ').replace(' ','')
        print('eval输出值: ',eval(express))
        if not express:
            continue
        elif express == 'q':
            exit()
        elif re.search('[^0-9.+-*/()]',express):
            print('33[31;1m输入错误33[0m')
        else:
            express=del_brackets(express)
            express2 = compute(format_mark(express))
            print('公式输出值: ',express2)

原文地址:https://www.cnblogs.com/SleepDragon/p/10413348.html