1.模块、包和相关语法使用模块有什么好处?
模块分类模块分为三种:
模块调用![]() import module from module import xx from module.xx.xx import xx as rename from module.xx.xx import *View Code 模块一旦被调用,即相当于执行了另外一个py文件里的代码 自定义模块这个最简单, 创建一个.py文件,就可以称之为模块,就可以在另外一个程序里导入 模块查找路径![]() import sys print(sys.path) ['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']View Code python解释器会按照列表顺序去依次到每个目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立刻导入,不再继续往后找。 注意列表第一个元素为空,即代表当前目录,所以你自己定义的模块在当前目录会被优先导入。 开源模块安装、使用https://pypi./pypi 是python的开源模块库 1.直接在上面这个页面上点download,下载后,解压并进入目录,执行以下命令完成安装 ![]() 编译源码 python setup.py build 安装源码 python setup.py installView Code 2.直接通过pip安装 ![]() pip3 install paramiko #paramiko 是模块名View Code pip命令会自动下载模块包并完成安装。 软件一般会被自动安装你python安装目录的这个子目录里 /your_python_install_path/3.6/lib/python3.6/site-packages pip命令默认会连接在国外的python官方服务器下载,速度比较慢,你还可以使用国内的豆瓣源,数据会定期同步国外官网,速度快好多 sudo pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com #alex_sayhi是模块名 使用下载后,直接导入使用就可以,跟自带的模块调用方法无差,演示一个连接linux执行命令的模块 ![]() #coding:utf-8 import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('192.168.1.108', 22, 'alex', '123') stdin, stdout, stderr = ssh.exec_command('df') print(stdout.read()) ssh.close(); 执行命令 - 通过用户名和密码连接服务器View Code 包(Package)当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹 . └── my_proj ├── crm #代码目录 │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── my_proj #配置文件目录 ├── settings.py ├── urls.py └── wsgi.py 像上面这样,一个文件夹管理多个模块文件,这个文件夹就被称为包,包就是文件夹,但该文件夹下必须存在 __init__.py 文件, 该文件的内容可以为空。__int__.py用于标识当前文件夹是一个包。 那不同包之间的模块互相导入呢? crm/views.py内容 ![]() def sayhi(): print('hello world!')View Code 通过manage.py调用 ![]() from crm import views views.sayhi()View Code 跨模块导入![]() import sys sys.path.append("C:\\Users\Administrator\PycharmProjects\myFirstpro\chapter4模块的学习\my_proj")#这个是静态路径,右键path它的路径。注意是找my_proj这个路径这样才能from.. ##如果加了proj这个路径,它就会自动往里边去找,直接import settings就可以了 #sys.path.append(r"C:\Users\Administrator\PycharmProjects\myFirstpro\chapter4模块的学习\my_proj") ##加r print(sys.path) from proj import settings def sayhi(): print('Hello World!')View Code ![]() import sys,os print(dir()) print(‘file’,_file_) BASE_DIR = os.path.dirname(os.path.dirname(_file_)) print(BASE_DIR) sys.path.append(BASE_DIR) #这个是动态路径 from proj import settings def sayhi(): print('Hello world!') 打印: ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'os', 'sys'] C:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模块的学习/my_proj/crm/views.py C:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模块的学习/my_proj in proj/settings.pyView Code ![]() import sys,os print(dir()) print(‘file’,_file_) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(_file_))) #这是绝对路径,这样在哪里执行都没有问题了 print(BASE_DIR) sys.path.append(BASE_DIR) from proj import settings def sayhi(): print('Hello world!')View Code 绝对导入&相对导入在linux里可以通过cd ..回到上一层目录 ,cd ../.. 往上回2层,这个..就是指相对路径,在python里,导入也可以通过 ![]() ├── __init__.py ├── crm │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ ├── views.py ├── manage.py └── proj ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py #from crm import models from . import models #from crm import models 这两个是一样的 #. 就叫相对导入,因为它俩在同一级目录 def sayhi(): print('Hello world!') #执行manageView Code
time & datetime 模块在python里通常有下面几种表示时间的方式:
索引(Index) 属性(Attribute) 值(Values) 0 tm_year(年) 比如2011 1 tm_mon(月) 1 - 12 2 tm_mday(日) 1 - 31 3 tm_hour(时) 0 - 23 4 tm_min(分) 0 - 59 5 tm_sec(秒) 0 - 61 6 tm_wday(weekday) 0 - 6(0表示周日) 7 tm_yday(一年中的第几天) 1 - 366 8 tm_isdst(是否是夏令时) 默认为-1 time.localtime()将当前时间转为当前时区的struct_time;wday 0-6表示周日到周六;ydat 1-366 一年中的第几天; isdst 是否为夏令时,默认为-1; time.gmtime() ![]() >>>import time >>>time.time() #返回当前的时间戳 1507808689.675603 >>>time.localtime() #将一个时间戳转换为当前时区的struct_time time.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=19, tm_min=45, tm_sec=61, tm_wday=3, tm_yday=285, tm_isdst=0) #打印本地时间 >>>time.gmtime() #将一个时间戳转换为UTC标准时间,比我们晚8个小时 time.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=11, tm_min=47, tm_sec=51, tm_wday=3, tm_yday=285, tm_isdst=0)View Code ![]() >>>a = time.localtime(1403232424) >>>a time.struct_time( tm_year=2014, tm_mon=6, tm_mday=20, tm_hour=10, tm_min=47, tm_sec=4, tm_wday=4, tm_yday=171, tm_isdst=0)View Code 字符串的拼接 、 time.mktime() ![]() >>>'%s-%s-%s'%(a.tm_year, a.tm_mon, a.tm_mday) #可以进行拼接 ‘2017-10-12’ >>>time.mktime(a) #将一个struct_time转化为时间戳。 140323242.0View Code time.asctime() (外国人常使用的时间形式) 、time.ctime()将当前时间转换为一个字符串str ![]() >>>time.asctime() #把一个表示时间的元组或者struct_time表示为这种形式:'Sun Oct 1 12:04:38 2017'。 'Thu Oct 12 19:52:10 2017' >>>time.ctime() #把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。相当于time.asctime(time.localtime(secs)) 'Thu Oct 12 19:52:36 2017' >>>time.ctime(123232) 'Fri Jan 2 18:13:52 1970' >>>time.ctime(0) 'Thu Jan 1 08:00:00 1970'View Code time.sleep(secs):线程推迟指定的时间运行。单位为秒。 time.strftime( ‘%Y-%m-%d %H:%M:%S %A %P %U’ ) 转化为格式化的字符串 time.strptime(s, ‘%Y-%m-%d %H:%M:%S ’ ) 把格式化字符串进行反转为struct_time time.strftime(a,b) , a为格式化字符串格式 , b为时间戳,一般用localtime() ![]() >>>a time.struct_time(tm_year=1974, tm_mon=6, tm_day=13, tm_hour=10, tm_min=40, tm_sec=42, tm_wday=3, tm_yday=164, tm_isdst=0) >>>time.strftime('%Y-%m-%d %H:%M:%S',a) #把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串 '1974-06-13 10:40:42' >>>time.strftime('%Y-%m-%d %H:%M:%S',) #不加就默认当前时间 '2017-10-12 19:56:31' >>>time.strftime('%Y-%m-%d %H:%M:%S %A',a) # %A 星期几 '1974-06-13 10:40:42 Thursday' >>>time.strftime('%Y-%m-%d %H:%M:%S %p',a) #%p AM or PM '1974-06-13 10:40:42 AM' >>>time.strftime('%Y-%m-%d %H:%M:%S %U',a) #%U一年的第几周 '1974-06-13 10:40:42 23' >>> import time >>> print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) 2018-07-28 14:12:17View Code ![]() >>>s=time.strftime('%Y-%m-%d %H:%M:%S') >>>s '2017 10-12 20:00:56' time.strptime(s, '%Y %m-%d %H:%M:%S') #反转 #把一个格式化时间字符串转化为struct_time time.struct_time(tm_year=2017, tm_mon=,10, tm_day=12, tm_hour=20, tm_min=1, tm_sec=26, tm_wday=3, tm_yday=285, tm_isdst=-1) >>>time.mktime(s) #把时间对象又变成时间戳 1507809686.0View Code datatime模块 datetime.datetime.now() 返回当前的datetime日期类型, ![]() >>>import datetime >>>datetime.datetime.now() #a.timestamp(),a.today(), a.year,a.timetuple()等方法可以调用;打印出下面的时间 datetime.datetime(2017, 10, 12, 20, 8, 19, 393189)View Code datetime.date.fromtimestamp() #把时间戳转化为datetime类型 ![]() >>>d2= datetime.date.fromtimestamp(time.time()) #快速的把时间戳拿到它的年月日 >>>d2 datetime.date(2017, 10, 12) >>>d2.timetuple() time.struct_time(tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=285, tm_isdst=-1) #其中三个为0,显示不了View Code 重点是进行时间的运算 datetime.datetime.now() (-) datetime.timedelta() ![]() >>>t = datetime.timedelta(1) >>>datetime.datetime.now() - t datetime.datetime(2017, 10, 11, 20, 12, 37, 106915) >>>datetime.datetime.now() - datetime.timedelta(days=1) datetime.datetime(2017, 10, 11, 20, 12, 37, 106915) >>>datetime.datetime.now() - datetime.timedelta(hours=3) datetime.datetime(2017, 10, 12, 17, 13, 14, 617201) >>>datetime.datetime.now() datetime.timedelta(minutes=10) datetime.datetime(2017, 10, 12, 20, 24, 2, 178282) >>>datetime.datetime.now() datetime.timedelta(seconds=10) datetime.datetime(2017, 10, 12, 20, 14, 23, 858086)View Code 时间的替换 ![]() >>>d.replace() datetime.datetime(2017, 10, 12, 20, 15, 17,457249) >>>d.replace(year=2016) datetime.datetime(2016, 10, 12, 20, 15, 17,457249) >>>d.replace(year=2016,month=8) datetime.datetime(2016, 8, 12, 20, 15, 17,457249)View Code random模块![]() >>> random.randrange(1,10) #返回1-10之间的一个随机数,不包括10 >>> random.randint(1,10) #返回1-10之间的一个随机数,包括10 >>> random.randrange(0, 100, 2) #随机选取0到100间的偶数 >>> random.random() #返回一个随机浮点数 >>> random.choice('abce3#$@1') #返回一个给定数据集合中的随机字符 '#' >>> random.sample('abcdefghij',3) #从多个字符中选取特定数量的字符 ['a', 'd', 'b'] #生成随机字符串 >>> import string >>> ''.join(random.sample(string.ascii_lowercase string.digits, 6)) '4fvda1' #洗牌 >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> random.shuffle(a) >>> a [3, 0, 7, 2, 1, 6, 5, 8, 9, 4]View Code os模块os 模块提供了很多允许你的程序与操作系统直接交互的功能 ![]() 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 函数用来删除一个文件:os.remove() 删除多个目录:os.removedirs(r“c:\python”) 检验给出的路径是否是一个文件:os.path.isfile() 检验给出的路径是否是一个目录:os.path.isdir() 判断是否是绝对路径:os.path.isabs() 检验给出的路径是否真地存:os.path.exists() 返回一个路径的目录名和文件名:os.path.split() e.g os.path.split('/home/swaroop/byte/code/poem.txt') 结果:('/home/swaroop/byte/code', 'poem.txt') 分离扩展名:os.path.splitext() e.g os.path.splitext('/usr/local/test.py') 结果:('/usr/local/test', '.py') 获取路径名:os.path.dirname() 获得绝对路径: os.path.abspath() 获取文件名:os.path.basename() 运行shell命令: os.system() 读取操作系统环境变量HOME的值:os.getenv("HOME") 返回操作系统所有的环境变量: os.environ 设置系统环境变量,仅程序运行时有效:os.environ.setdefault('HOME','/home/alex') 给出当前平台使用的行终止符:os.linesep Windows使用'\r\n',Linux and MAC使用'\n' 指示你正在使用的平台:os.name 对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix' 重命名:os.rename(old, new) 创建多级目录:os.makedirs(r“c:\python\test”) 创建单个目录:os.mkdir(“test”) 获取文件属性:os.stat(file) 修改文件权限与时间戳:os.chmod(file) 获取文件大小:os.path.getsize(filename) 结合目录名与文件名:os.path.join(dir,filename) 改变工作目录到dirname: os.chdir(dirname) 获取当前终端的大小: os.get_terminal_size() 杀死进程: os.kill(10884,signal.SIGKILL)View Code sys模块![]() sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称 sys.stdout.write('please:') #标准输出 , 引出进度条的例子, 注,在py3上不行,可以用print代替 val = sys.stdin.readline()[:-1] #标准输入 sys.getrecursionlimit() #获取最大递归层数 sys.setrecursionlimit(1200) #设置最大递归层数 sys.getdefaultencoding() #获取解释器默认编码 sys.getfilesystemencoding #获取内存数据存到文件里的默认编码View Code shutil模块高级的 文件、文件夹、压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length]) ![]() import shutil shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))View Code shutil.copyfile(src, dst) ![]() shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在View Code shutil.copymode(src, dst) ![]() shutil.copymode('f1.log', 'f2.log') #目标文件必须存在View Code shutil.copystat(src, dst) ![]() shutil.copystat('f1.log', 'f2.log') #目标文件必须存在View Code shutil.copy(src, dst) ![]() import shutil shutil.copy('f1.log', 'f2.log')View Code shutil.copy2(src, dst) ![]() import shutil shutil.copy2('f1.log', 'f2.log')View Code shutil.ignore_patterns(*patterns) ![]() import shutil shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除View Code shutil.rmtree(path[, ignore_errors[, onerror]]) ![]() import shutil shutil.rmtree('folder1')View Code shutil.move(src, dst) ![]() import shutil shutil.move('folder1', 'folder3')View Code shutil.make_archive(base_name, format,...)
如 data_bak =>保存至当前路径
![]() #将 /data 下的文件打包放置当前程序目录 import shutil ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data') #将 /data下的文件打包放置 /tmp/目录 import shutil ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')View Code shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细: ![]() import zipfile # 压缩 z = zipfile.ZipFile('laxi.zip', 'w') z.write('a.log') z.write('data.data') z.close() # 解压 z = zipfile.ZipFile('laxi.zip', 'r') z.extractall(path='.') z.close()View Code tarfile压缩&解压缩 ![]() import tarfile # 压缩 >>> t=tarfile.open('/tmp/egon.tar','w') >>> t.add('/test1/a.py',arcname='a.bak') >>> t.add('/test1/b.py',arcname='b.bak') >>> t.close() # 解压 >>> t=tarfile.open('/tmp/egon.tar','r') >>> t.extractall('/egon') >>> t.close()View Code 序列化模块序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes 用于序列化的两个模块
JSON: 优点:跨语言、体积小 缺点:只能支持int\str\list\tuple\dict Pickle: 优点:专为python设计,支持python所有的数据类型 缺点:只能在python中使用,存储数据占空间大
Json模块提供了四个功能:dumps、dump、loads、load pickle模块提供了四个功能:dumps、dump、loads、load ![]() import pickle data = {'k1':123,'k2':'Hello'} # pickle.dumps 将数据通过特殊的形式转换位只有python语言认识的字符串 p_str = pickle.dumps(data) print(p_str) #pickle.dump 将数据通过特殊的形式转换位只有python语言认识的字符串,并写入文件 with open('D:/result.pk','wb',encoding='utf8') as fp: pickle.dump(data,fp) import json # json.dumps 将数据通过特殊的形式转换位所有程序语言都认识的字符串 j_str = json.dumps(data) print(j_str) #pickle.dump 将数据通过特殊的形式转换位只有python语言认识的字符串,并写入文件 with open('D:/result.json','wb',encoding='utf8') as fp: json.dump(data,fp)View Code ![]() #序列化 data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'关羽','life':80}, ] } f = open('game_status','w') f.write(str(data)) #str把字典转换成字符串View Code ![]() #反序列 把字符转成内存数据类型 data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'关羽','life':80}, ] } # f = open('game_status','w') # f.write(str(data)) f = open('game_status','r') d = f.read() d = eval(d) #字符串转成字典 print(d['roles'])View Code 序列化json模块![]() import json data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'关羽','life':80}, ] } d = json.dumps(data) #仅换成字符串 print(d,type(d)) #str d2 = json.loads(d) #把字符串转成相应的数据类型 print(d2,type(d2)) #dict print(d2['roles'])View Code ![]() 打印: {"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]} <class 'str'> {'roles': [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]} <class 'dict'> [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]View Code 注意loads和load、 dumps和dump的用法和区别: dumps是将dict转化成str格式,loads是将str转化成dict格式。dump和load也是类似的功能,只是与文件操作结合起来了。 ![]() import json data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'关羽','life':80}, ] } f = open("test.json", "w") json.dump(data, f) #转成字符串并写入文件 f = open("test.json","r") data = json.load(f) # print(data['roles'])View Code ![]() 自动生成一个test.json文件夹 {"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]} 打印出: [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '关羽', 'life': 80}]View Code 只把数据类型转换成字符串存到内存里的意义? json.dumps json.loads 1.把你的内存数据,通过网络,共享给远程其他人; 2.定义了不同语言的之前的交互规则。 1.纯文本, 坏处, 不能共享复杂的数据类型; 2.xml, 坏处 , 占空间大;3.json, 简单, 可读性好。 ![]() import json f = open('json_file', 'w', encoding='utf-8') d = {'name':'alex', 'age':'23'} #字典 l = [1,2,3,5,9,'rain'] #列表 json.dump(d,f) #可以dump多次 json.dump(l,f) 自动创建json_file的文件: {"name": "alex", "age": "23"}[1, 2, 3, 5, 9, "rain"]View Code ![]() import json f = open("json_file", 'r', encoding"utf-8") print(json.load(f)) #反序列化不能load多次,不要dump多次,load多次。只一次,为了避免问题。 json_load文件里边字典和列表都在里边不能load,会报错。View Code pickle(用法完全一样)![]() import pickle d = {'name' : 'alex' , 'age' : 22 } l = [1,2,3,4,'rain' ] pk = open("data.pkl", "w") print(pickle.dumps(d)) ##打印bytes类型 b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00alexq\x02X\x03\x00\x00\x00ageq\x03K\x16u.'View Code ![]() import pickle d = {'name' : 'alex' , 'age' : 22 } l = [1,2,3,4,'rain' ] pk = open("data.pkl", "wb") print(pickle.dump(d,pk)) #二进制的bytes类型的文本格式,存到了硬盘上。 print(pickle.dump(l,pk) 自动创建data.pkl文件夹: �}q (X nameq X alexq X ageq K u. �]q (K K K K X rainq e.View Code 从硬盘上读取数据 ![]() import pickle f = open("data.pkl", "rb") d = pickle.load(f) print(d) #{'name': 'alex', 'age': 22} l = pickle.load(f) print(l) #[1, 2, 3, 4, 'rain']View Code 序列化shelve模块shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 ![]() #序列化 import shelve f = shelve.open('shelve_test') # 打开一个文件 names = ["alex", "rain", "test"] info = {'name':'alex','age':22} f["names"] = names # 持久化列表 f['info_dic'] = info #持久化dict f.close() #反序列化 import shelve d = shelve.open('shelve_test') # 打开一个文件 print(d['names']) #['alex', 'rain', 'test'] print(d['info_dic']) #{'name': 'alex', 'age': 22} #del d['test'] #还可以删除View Code ![]() >>>f = shelve.open("shelve_test") >>>f <shelve.DbfilenameShelf object at 0x101dce9e8> >>>list(f.keys()) ['name', 'info_dic'] >>>list(f.items()) [('name', ['alex', 'rain', 'test']), ('info_dic', {'name': 'alex', 'age':22})] >>>f.get('names') ['alex', 'rain', 'text'] >>>f.get('info_dic') {'name': 'alex', 'age':22} >>>f['names'][1] 'rain' >>>f['names'][1] = "Rain wang" #不能这样修改,修改不了,要直接赋值。 >>>f['names'][1] None >>>f.close() >>>f = shelve.open("shelve_test")View Code ![]() import shelve f = shelve.open("shelve_test") f['scores'] = [1,2,3,4,5,6] print(f.get('scores')) f['scores'] = [1,2,3,'A',4,'B'] print(f.get('scores'))View Code XML模块xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是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>View Code ![]() import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") #open root = tree.getroot() #f.seek(0) print(root.tag) #遍历xml文档 for child in root: print('-------------',child.tag,child.attrib) #print(child.tag, child.attrib) for i in child: print(i.tag,i.text) 打印: data ------------- country {'name': 'Liechtenstein'} rank 2 year 2008 gdppc 141100 neighbor None neighbor None ------------- country {'name': 'Singapore'} rank 5 year 2011 gdppc 59900 neighbor None ------------- country {'name': 'Panama'} rank 69 year 2011 gdppc 13600 neighbor None neighbor NoneView Code ![]() import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") #open root = tree.getroot() #f.seek(0) print(root.tag) #只遍历year 节点 for node in root.iter('year'): print(node.tag,node.text) 打印: data year 2008 year 2011 year 2011View Code ![]() ###################自己创建xml文档############################# import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") #root name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") n = ET.SubElement(name,"name") n = "alex" sex.text = 'man' 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>man</sex></name> <name enrolled="no"> <age>19</age> </name></namelist>View Code configparser模块(解析、配置文件)此模块用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser。 好多软件的常见配置文件格式如下: ![]() ##conf.ini文件 [DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = noView Code ![]() >>> import configparser >>> config = configparser.ConfigParser() #实例化生成一个对象 >>> config.sections() #调用sections方法;在cmd里边演示 [] >>> config.read('example.ini') ['example.ini'] >>> config.sections() #调用sections方法(默认不会读取default方法) ['bitbucket.org', 'topsecret.server.com'] >>> 'bitbucket.org' in config #判断元素是否在sections列表内 True >>> 'bytebong.com' in config False >>> config['bitbucket.org']['User'] #通过字典的形式取值 'hg' >>> config['DEFAULT']['Compression'] 'yes' >>> topsecret = config['topsecret.server.com'] >>> topsecret['ForwardX11'] 'no' >>> topsecret['Port'] '50022' >>> for key in config['bitbucket.org']: print(key) #for循环bitbucket.org 字典的key ... user compressionlevel serveraliveinterval compression forwardx11 >>> config['bitbucket.org']['ForwardX11'] 'yes'View Code ![]() import configparser conf = configparser.ConfigParser() #先生成一个对象 #print(conf.sections()) #[] conf.read('conf.ini') print(conf.sections())#['bitbucket.org', 'topsecret.server.com'] print(conf.default_section) #DEFAULT # print(list(conf["bitbucket.org"].keys())) print(conf["bitbucket.org"]['User']) #hgView Code ![]() #循环 import configparser conf = configparser.ConfigParser() #先生成一个对象 conf.read('conf.ini') for k,v in conf["bitbucket.org"].items(): print(k,v) #打印: user hg serveraliveinterval 45 compression yes compressionlevel 9 forwardx11 yesView Code ![]() import configparser conf = configparser.ConfigParser() conf.read('conf.ini') if 'user' in conf["bitbucket.org"]: #判断是否在 print('in')View Code ![]() import configparser conf = configparser.ConfigParser() #先生成一个对象 conf.read("conf_text.ini") conf.add_section("group3") conf["group3"]['name'] = "alex" conf["group3"]['age'] = '22' conf.write(open('conf_test_mew.ini','w')) ###改写View Code ![]() import configparser conf = configparser.ConfigParser() #先生成一个对象 conf.read("conf_text.ini") #conf.remove_option("group1",'k2') conf.remove_section("group1") conf.write(open('conf_test2_mew.ini','w'))#删完之后要保存View Code hashlib模块加密算法介绍HASHHash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。 简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值.也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系 MD5什么是MD5算法 MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位的散列值(hash value),用于确保信息传输完整一致。MD5的前身有MD2、MD3和MD4。 MD5功能 输入任意长度的信息,经过处理,输出为128位的信息(数字指纹); MD5算法的特点
MD5算法是否可逆? MD5不可逆的原因是其是一种散列函数,使用的是hash算法,在计算过程中原文的部分信息是丢失了的。 MD5用途
SHA-1安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。 SHA是美国国家安全局设计的,由美国国家标准和技术研究院发布的一系列密码散列函数。 由于MD5和SHA-1于2005年被山东大学的教授王小云破解了,科学家们又推出了SHA224, SHA256, SHA384, SHA512,当然位数越长,破解难度越大,但同时生成加密的消息摘要所耗时间也更长。目前最流行的是加密算法是SHA-256 . MD5与SHA-1的比较由于MD5与SHA-1均是从MD4发展而来,它们的结构和强度等特性有很多相似之处,SHA-1与MD5的最大区别在于其摘要比MD5摘要长32 比特。对于强行攻击,产生任何一个报文使之摘要等于给定报文摘要的难度:MD5是2128数量级的操作,SHA-1是2160数量级的操作。产生具有相同摘要的两个报文的难度:MD5是264是数量级的操作,SHA-1 是280数量级的操作。因而,SHA-1对强行攻击的强度更大。但由于SHA-1的循环步骤比MD5多80:64且要处理的缓存大160比特:128比特,SHA-1的运行速度比MD5慢。 Python的 提供的相关模块用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 ![]() import hashlib m = hashlib.md5() m.update(b"Hello") m.update(b"It's me") print(m.digest()) m.update(b"It's been a long time since last time we ...") print(m.digest()) #2进制格式hash print(len(m.hexdigest())) #16进制格式hash ''' def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ pass def hexdigest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of hexadecimal digits. """ pass ''' import hashlib # ######## md5 ######## hash = hashlib.md5() hash.update('admin') print(hash.hexdigest()) # ######## sha1 ######## hash = hashlib.sha1() hash.update('admin') print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256() hash.update('admin') print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384() hash.update('admin') print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512() hash.update('admin') print(hash.hexdigest())View Code hashlib md5值的用法 ![]() #加入下面这个就可以 password = input('请输入密码:') m = hashlib.md5() m.update(password.encode()) if m.hexdigest() == data1['password']: print('登录成功')View Code subprocess模块我们经常需要通过Python去执行一条系统命令或脚本,系统的shell命令是独立于你的python进程之外的,每执行一条命令,就是发起一个新进程,通过python调用系统命令或脚本的模块在python2有os.system, >>> os.system('uname -a') Darwin Alexs-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun 4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_64 0 三种执行命令的方法
run方法 ![]() #标准写法 subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True) #涉及到管道|的命令需要这样写 subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是这条命令直接交给系统去执行,不需要python负责解析View Code call()方法![]() #执行命令,返回命令执行状态 , 0 or 非0 >>> retcode = subprocess.call(["ls", "-l"]) #执行命令,如果命令结果为0,就正常返回,否则抛异常 >>> subprocess.check_call(["ls", "-l"]) #接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #接收字符串格式命令,并返回结果 >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res >>> res=subprocess.check_output(['ls','-l']) >>> res b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'View Code Popen()方法常用参数:
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE) a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
区别是Popen会在发起命令后立刻返回,而不等命令执行结果。这样的好处是什么呢? 如果你调用的命令或脚本 需要执行10分钟,你的主程序不需卡在这里等10分钟,可以继续往下走,干别的事情,每过一会,通过一个什么方法来检测一下命令是否执行完成就好了。 Popen调用后会返回一个对象,可以通过这个对象拿到命令执行结果或状态等,该对象有以下方法
Check if child process has terminated. Returns returncode
Wait for child process to terminate. Returns returncode attribute.
>>> a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True) >>> a.communicate(b'22') (b'your guess:try bigger\n', b'')
logging模块 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 ![]() #最简单用法 import logging logging.warning("user [alex] attempted wrong password more than 3 times") logging.critical("server is down")View Code ![]() #输出 WARNING:root:user [alex] attempted wrong password more than 3 times CRITICAL:root:server is downView Code 如果想把日志写到文件里,也很简单![]() import logging logging.basicConfig(filename='example.log',level=logging.INFO) logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too')View Code 其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了.
自定义日志格式
感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上! ![]() import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') logging.warning('is when this event was logged.') #输出 12/12/2010 11:46:36 AM is when this event was logged.View Code 日志同时输出到屏幕和文件如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了 Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
他们之间的关系是这样的
logger每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger: LOG=logging.getLogger(”chat.gui”) 而核心模块可以这样: LOG=logging.getLogger(”chat.kernel”) 还可以绑定handler和filters Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高 Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别 handlerhandler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Handler可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略 Handler.setFormatter():给这个handler选择一个格式 Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) 其中filename和mode两个参数和FileHandler一样。
logging.handlers.TimedRotatingFileHandler 这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的函数是: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
formatter 组件日志的formatter是个独立的组件,可以跟handler组合 fh = logging.FileHandler("access.log") formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) #把formmater绑定到fh上
filter 组件如果你想对日志内容进行过滤,就可自定义一个filter class IgnoreBackupLogFilter(logging.Filter): """忽略带db backup 的日志""" def filter(self, record): #固定写法 return "db backup" not in record.getMessage() #注意filter函数会返加True or False,logger根据此值决定是否输出此日志 然后把这个filter添加到logger中 logger.addFilter(IgnoreBackupLogFilter()) 下面的日志就会把符合filter条件的过滤掉 logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....") 一个同时输出到屏幕、文件、带filter的完成例子 ![]() import logging class IgnoreBackupLogFilter(logging.Filter): """忽略带db backup 的日志""" def filter(self, record): #固定写法 return "db backup" not in record.getMessage() #console handler ch = logging.StreamHandler() ch.setLevel(logging.INFO) #file handler fh = logging.FileHandler('mysql.log') #fh.setLevel(logging.WARNING) #formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') #bind formatter to ch ch.setFormatter(formatter) fh.setFormatter(formatter) logger = logging.getLogger("Mysql") logger.setLevel(logging.DEBUG) #logger 优先级高于其它输出途径的 #add handler to logger instance logger.addHandler(ch) logger.addHandler(fh) #add filter logger.addFilter(IgnoreBackupLogFilter()) logger.debug("test ....") logger.info("test info ....") logger.warning("start to run db backup job ....") logger.error("test error ....")View Code 文件自动截断例子 ![]() import logging from logging import handlers logger = logging.getLogger(__name__) log_file = "timelog.log" #fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3) fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3) formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) logger.warning("test1") logger.warning("test12") logger.warning("test13") logger.warning("test14")View Code re模块 正则表达式就是字符串的匹配规则,在多数编程语言里都有相应的支持,python里对应的模块是re 常用的表达式规则'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 会匹配到foo1 '*' 匹配*号前的字符0次或多次, re.search('a*','aaaabac') 结果'aaaa' ' ' 匹配前一个字符1次或多次,re.findall("ab ","ab cd abb bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次 '{m}' 匹配前一个字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb' '{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|45)", "abcabca456c").group() 结果为'abcabca45' '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的,相当于re.match('abc',"alexabc") 或^ '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s ","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'} re的匹配语法有以下几种
软件开发目录规范Foo/ |-- bin/ | |-- foo | |-- foo/ | |-- tests/ | | |-- __init__.py | | |-- test_main.py | | | |-- __init__.py | |-- main.py | |-- docs/ | |-- conf.py | |-- abc.rst | |-- setup.py |-- requirements.txt |-- README
简要解释一下:
conf 存配置文件的,(账户数据、日志的文件名或者格式,这些用户可以配置的;) 来源:http://www./content-4-27711.html |
|