Python模块
模块(module)
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为一个模块(Module)
而在Python中的module分为三种:
- Python标准库
- 第三方模块
- 应用自定义模块
引用方法
import modname
##引用本地目录的module
from modname import name1[, name2[, ... nameN]]
from filename.filename… import modname
##引用那个指定目录下的module
from modname import *
##引用该module里面所有的函数
>>> import sys
>>> print(sys.path)
['', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36\\Lib\\idlelib', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\DELL\\AppData\\Roaming\\Python\\Python36\\site-packages', 'C:\\Users\\DELL\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages']
##import的运行本质的在sys.path里面的路径找module
包(Package)
每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录(文件夹),而不是一个包.要避免与同级目录的Package重名.
print(__file__)##该结果是当前的文件
import sys,os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
##os.path.dirname() 返回上一级, os.path.abspath() 绝对路径
sys.path.append(BASE_DIR) ##把该路径暂时放到系统path里面,就能找到了
import hello
hello.hello1()
防止程序被引用
##写在这下面的程序,可以防止被其他调用运行,也可以用于被调用函数的测试
if __name__ == "main":
program
—-time模块
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) #---------------------------------------------------------- # 3 gmtime([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 2016 print(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 random
print(random.random())
##返回[0,1)之间的任意浮点数
print(random.randint(1,10))
##返回[1,10]之间的任意整数
print(random.randrange(1,100,2))
##从指定范围内,按指定基数递增的集合中获取一个随机数
print(random.choice([1,'23',[4,5]]))
##在sequence里面选择一个
print(random.sample([1,'23',[4,5]],2))
##从指定序列中随机获取指定长度的片段,sample函数不会修改原有序列
print(random.uniform(1,3))
##用于生成一个指定范围内的随机浮点数
item=[1,3,5,7,9]
random.shuffle(item)
print(item)
##用于打乱序列
—-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下为"\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不存在,返回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所指向的文件或者目录的最后修改时间
—-sys模块
import sys sys.argv #命令行参数List,第一个元素是程序本身路径 sys.exit(n) #退出程序,正常退出时exit(0) sys.version #获取Python解释程序的版本信息 sys.maxint #最大的Int值 sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform #返回操作系统平台名称
—-json模块
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling;序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上;反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling
import json
dic = {"name":"Hermaeus",
"age":19,
"hometown":"MeiShan",
"hobby":"Coding"}
j_dic = json.dumps(dic) #===> json.dump(dic, f)
f = open("test.json","w")
f.write(j_dic)
f.close()
import json
f = open("test.json","r")
date = json.loads(f.read()) #===> json.load(f)
print(date)
输入结果为:
{'name': 'Hermaeus', 'age': 19, 'hometown': 'MeiShan', 'hobby': 'Coding'}
—-pickle模块
import pickle
#----------------------序列化------------------------
dic = {"name":"Hermaeus",
"age":19,
"hometown":"MeiShan",
"hobby":"Coding"}
j_dic = pickle.dumps(dic)
f = open("test.json","wb") #必须输入二进制
f.write(j_dic) #===>pickle.dump(dic, f)
f.close()
#---------------------反序列化------------------------
f = open("test.json","rb") #输入的也一定是二进制
date = pickle.loads(f.read()) #===>pickle.load(f)
print(date)
—-shelve模块
##类字典操作
import shelve
f = shelve.open(r"shelve.txt") #就一个open函数
f["info_1"] = {"name":"Hermaeus", "age":19}
f["info_2"] = {"name":"YuanMing", "age":20}
# f.close()
print(f["info_1"])
print(f["info_2"]["name"])
—-xml模块
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>
操作如下:
import xml.etree.ElementTree as ET
tree = 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 ET
tree = 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")
#删除node
for 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 ET
new_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 version='1.0' encoding='utf-8'?>
<namelist>
<name enrolled="yes">
<age checked="no" />
<sex>33</sex>
</name>
<name enrolled="no">
<age>19</age>
</name>
</namelist>
configparser模块
##类字典操作
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
'Compression': 'yes',
'CompressionLevel': '9'
}
config["bitbucket"] = {}
config["bitbucket"]["user"] = "hg"
config["topsecret.server.com"] = {}
topsecret = config["topsecret.server.com"]
topsecret["Host Port"] = '32204'
topsecret["Fowardx11"] = "no"
config["DEFAULT"]["Fowardx11"] = "yes"
with open("example.ini", "w") as configfile:
config.write(configfile)
得到结果:
[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
fowardx11 = yes
[bitbucket]
user = hg
[topsecret.server.com]
host port = 32204
fowardx11 = no
其他操作
import configparser
config = configparser.ConfigParser()
config.read("example.ini")
print(config.sections()) #sections()是获得非DEFAULT的值
['bitbucket', 'topsecret.server.com']
print("bytebong.com" in config)
False
print(config["bitbucket"]["user"])
hg
print(config["DEFAULT"]["Compression"])
yes
print(config["topsecret.server.com"]["Fowardx11"])
no
for key in config["bitbucket"]: #每一次打印都会把DEFAULT里面的值打印下来
print(key)
user
serveraliveinterval
compression
compressionlevel
fowardx11
print(config.options("bitbucket")) #返回键
['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'fowardx11']
print(config.items("bitbucket")) #把键值对以元组方式输出
[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('fowardx11', 'yes'), ('user', 'hg')]
print(config.get("bitbucket", "compression")) #返回bitbucket里面是否有compression
yes
config.add_section("answer") #建立一个section
config.remove_section("topsecret.server.com") #删除一个section
config.remove_option("bitbucket", "user") #删除一个键
config.set("bitbucket", "k1", "111") #增添一个键值对
config.write(open("i.cfg", "w")) #写入磁盘
—-hashlib
用于加密相关的操作,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlib
m = hashlib.md5()
m.update("hello".encode("utf-8"))
print(m.hexdigest())
5d41402abc4b2a76b9719d911017c592
m.update("hello".encode("utf-8"))
m.update("world!".encode("utf-8")) ##等同于"helloworld!",这样是把它们两个拼接在一起
print(m.hexdigest())
420e57b017066b44e05ea1577f6e2e12
m.update("helloworld!".encode("utf-8"))
print(m.hexdigest())
420e57b017066b44e05ea1577f6e2e12
然后这种加密,可以通过撞库来反解,但是可以在加密算法里添加自定义key再来加密
import hashlib
m = hashlib.sha256("ok".encode("utf-8"))
m.update("hello".encode("utf-8"))
print(m.hexdigest())
ce9eba905e14b4f0dceb89f329280c10bb0403375d2a613c4bfb8aa726145c73
—-logging模块
import logging
logging.debug("debug message")
logging.info("info message")
logging.warning("waring message")
logging.error("error message")
logging.critical("critical message")
WARNING:root:waring message
ERROR:root:error message
CRITICAL:root:critical message
##在默认情况下,输入显示的是大于等于warning级别的(critical>error>warning>info>debug)
import logging
logging.basicConfig(level = logging.DEBUG,
format = "%(asctime)s, %(filename)s[line:%(lineno)d] %(levelname)s %(message)s",
datefmt = "%a %d %b %Y %H:%M:%S",
filename = "test.log",
filemode = "w")
logging.debug("debug message")
logging.info("info message")
logging.warning("waring message")
logging.error("error message")
logging.critical("critical message")
输入结果如下,
Thu 16 Aug 2018 12:48:50, experiment.py[line:1762] DEBUG debug message
Thu 16 Aug 2018 12:48:50, experiment.py[line:1763] INFO info message
Thu 16 Aug 2018 12:48:50, experiment.py[line:1764] WARNING waring message
Thu 16 Aug 2018 12:48:50, experiment.py[line:1765] ERROR error message
Thu 16 Aug 2018 12:48:50, experiment.py[line:1766] CRITICAL critical message
可见在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,‘w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息
logger对象
import logging
logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 定义一个filter
filter = logging.Filter('mylogger')
fh.addFilter(filter)
ch.addFilter(filter)
# logger.addFilter(filter)
logger.addHandler(fh)
logger.addHandler(ch)
logger.setLevel(logging.DEBUG)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)
logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)
logger1.addHandler(fh)
logger1.addHandler(ch)
logger2.addHandler(fh)
logger2.addHandler(ch)
logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
—-re模块
re的元字符
import re
ret = re.findall("e..a", "Hermaeus") #"."是模糊表示一个字符
print(ret)
['erma']
ret = re.findall("^H..m", "Hermaeus") #"^"表示开头必须是某个字符
print(ret)
['Herm']
ret = re.findall("a..s$", "Hermaeus") #"$"表示结尾必须是1某个字符
print(ret)
['aeus']
ret = re.findall("abc*", "abccccc") #贪婪匹配[0,+∞]
print(ret)
['abccccc']
ret = re.findall("abc+", "abccccc") #贪婪匹配[1,+∞]
print(ret)
['abccccc']
ret = re.findall("abc?", "abccccc") #惰性匹配[0,1]
print(ret)
['abc']
ret = re.findall("abc{1,3}", "abccccc") #贪婪匹配[1,3]
print(ret)
['abccc']
ret = re.findall("abc*?", "abccccc") #这样会让其变成惰性匹配
print(ret)
['ab']
字符集===>“[ ]”
即在字符集中任意匹配一个
import re
ret = re.findall("a[bc]", "abc")
print(ret)
['ab']
ret = re.findall("[a-z]", "ahfao")
print(ret)
['a', 'h', 'f', 'a', 'o']
ret = re.findall("[%$]", "ada%jf$") #在字符集里面除了:- ^ \以外都是普通字符
print(ret)
['%', '$']
##" - " 取在这之间的
ret = re.findall("[1-9]", "1jkah1k2k3j")
print(ret)
['1', '1', '2', '3']
##" ^ " 取反,即在这字符集里面没有的
ret = re.findall("[^ab]", "7ajkf2bfjab")
print(ret)
['7', 'j', 'k', 'f', '2', 'f', 'j']
##" \ " 转义符
ret = re.findall("[\d]", "45dhaf2")
print(ret)
['4', '5', '2']
转义符
反斜杠后边跟元字符去除特殊功能,比如\. 反斜杠后边跟普通字符实现特殊功能,比如\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 匹配一个特殊字符边界,比如空格 ,&,#等
import re
ret = re.findall(r"I\b", "I am LIST") ##添加"r",表示把需要匹配的字符集直接交给模块处理
print(ret)
分组 “( )”
import re
ret = re.search("(?P<id>\d{2})/(?P<name>\w{3})", "23/com") #"?P<id> 取名
print(ret)
<_sre.SRE_Match object; span=(0, 6), match='23/com'> #返回一个对象
print(ret.group())
23/com
print(ret.group("id"))
23
“|”符号
import re
ret = re.search("(ab)|\d", "rabjk4fk") #二选一
print(ret)
print(ret.group())
re下的常用方法
import re
#1
re.findall('a','alvin yuan') #返回所有满足匹配条件的结果,放在列表里
#2
re.search('a','alvin yuan').group() #函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以;通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
#3
re.match('a','abc').group() #同search,不过尽在字符串开始处进行匹配
#4
ret=re.split('[ab]','abcd') #先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
print(ret)#['', '', 'cd']
#5
ret=re.sub('\d','abc','alvin5yuan6',1)
print(ret)#alvinabcyuan6 #替代
ret=re.subn('\d','abc','alvin5yuan6')
print(ret)#('alvinabcyuanabc', 2) #替代,且可以选择次数
#6
obj=re.compile('\d{3}') #对象赋予
ret=obj.search('abc123eeee')
print(ret.group())#123
#7
ret=re.finditer('\d','ds3sy4784a')
print(ret) #<callable_iterator object at 0x10195f940>
#返回迭代器
print(next(ret).group())
print(next(ret).group())
注意:
import re
ret=re.findall('www.(baidu|oldboy).com','www.oldboy.com')
print(ret)['oldboy'] #这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
['oldboy']
ret=re.findall('www.(?:baidu|oldboy).com','www.oldboy.com')
print(ret)
['www.oldboy.com']