Python3基础之学习笔记(六)-json与pickle数据序列化-项目目录结构-模块详解

1. json与pickle数据序列化

1.1 json序列化与反序列化

1.1.1 json序列化

import json
def main():
    info={
        'name':'ming',
        'age':18
    }
    with open('test','w') as f:
        print(json.dumps(info))#json序列化
        f.write(json.dumps(info))
if __name__ == "__main__":
    main()

1.1.2 json反序列化

import json
 
def main():
    with open('test','r') as f:
        data=json.loads(f.read())#json反序列化
        print(data)
if __name__ == "__main__":
    main()

1.1.3 json小结

Json只能进行简单类型的序列化,如字典,列表,只dump一次,只load一次

1.2 pickle序列化与反序列化

1.2.1 pickle序列化

import pickle
def fun1():
    print('Hello World!')
def main():
    info={
        'name':"ming",
        'age':18,
        'fun':fun1
    }
    with open('test1','wb') as f:
        f.write(pickle.dumps(info))#pickle只能在python里面用,支持任意数据类型
         #pickle.dump(info,f)#和上面结果一样
if __name__ == "__main__":
    main()

1.2.2 pickle反序列化

import pickle
def fun1():
    print('Hello World!')
def main():
    with open('test1','rb') as f:
        data=pickle.loads(f.read())
        #data=pickle.load(f)#和上面结果一样
if __name__ == "__main__":
    main()

1.2.3 pickle小结

pickle只能在python里面用,支持任意数据类型

2. 项目目录结构

假设你的项目名为foo

Foo/
|-- bin/
|   |-- foo
|
|--config/
|  |-- config.py
|-- foo/
|   |-- tests/
|   |   |-- __init__.py
|   |   |-- test_main.py
|   |
|   |-- __init__.py
|   |-- main.py
|
|-- docs/
|   |-- conf.py
|   |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README

简单介绍下:

  1. bin/: 存放项目的一些可执行文件 。
  2. config/:存放配置文件目录。
  3. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
  4. docs/: 存放一些文档。
  5. setup.py: 安装、部署、打包的脚本。
  6. requirements.txt: 存放软件依赖的外部Python包列表,可以通过pip install -r requirements.txt来把所有Python包依赖都装好。
  7. README: 项目说明文件。

3. 模块详解

3.1 模块定义

模块:本质就是.py结尾的python文件,用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能)

包:用来从逻辑上组织模块的,本质就一个目录(必须带有一个__init__.py文件)

3.2 模块导入方法

#导入一个模块,相当于将模块所有代码解释一遍赋给一个变量,该变量名就是模块名,调用方法时需要加模块名
import 模块名
#导入多个模块
import 模块1,模块2
#导入一个模块所有方法,相当于把那个模块代码导入到本模块所有代码前面(不建议使用)
from 模块名 import *
#导入一个模块某一个方法,调用方法时直接使用方法名
from 模块名 import 方法名
#设置别名
from 模块名 import 方法名 as 方法别名
#从当前目录下导入模块
from . import 模块名
#导入一个包
import 包名
#从包导入模块
from 包名 import 模块名

3.3 import本质

  • 导入模块的本质就是先查找搜索路径(sys.path),再把python文件解释一遍。
  • 导入包的本质就是执行该包下的__init__.py(该文件用于导入该包下其它的模块)文件。
  • 导入包和导入模块是不一样的。

3.4 标准模块

3.4.1 time与datetime模块

在Python中通常有这几种方式表示时间:

  • 时间戳
  • 格式化的时间字符串
  • 元组
In [1]: import time
In [2]: import datetime
 
In [3]: time.time()#获取时间戳
Out[3]: 1534407920.3427649
 
In [4]: time.localtime(time.time())#获取本地时间元组
Out[4]: time.struct_time(tm_year=2018, tm_mon=8, tm_mday=16, tm_hour=16, tm_min=27, tm_sec=22, tm_wday=3, tm_yday=228, tm_isdst=0)
 
In [5]: time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())#获取格式化的时间字符串
Out[5]: '2018-08-16 16:28:14'
 
In [6]: time.timezone#世界时间与本地时间差值
Out[6]: -28800
 
In [7]: time.daylight#是否使用夏令时
Out[7]: 0
 
In [8]: time.sleep(2)#延时2秒
 
In [9]: time.gmtime()#获取UTC时区的元组
Out[9]: time.struct_time(tm_year=2018, tm_mon=8, tm_mday=16, tm_hour=8, tm_min=58, tm_sec=24, tm_wday=3, tm_yday=228, tm_isdst=0)
 
In [10]: time.strptime('2018-08-16 16:28:14','%Y-%m-%d %H:%M:%S')#时间字符串转元组
Out[10]: time.struct_time(tm_year=2018, tm_mon=8, tm_mday=16, tm_hour=16, tm_min=28, tm_sec=14, tm_wday=3, tm_yday=228, tm_isdst=-1)
 
In [12]: time.mktime(time.localtime(time.time()))#将元组转换成时间戳
Out[12]: 1534411002.0
 
In [14]: time.asctime()#接收的参数是元组
Out[14]: 'Thu Aug 16 16:38:32 2018'
 
In [15]: time.ctime()#接收的是时间戳
Out[15]: 'Thu Aug 16 16:39:28 2018'
 
In [16]: datetime.datetime.now()#获取当前时间
Out[16]: datetime.datetime(2018, 8, 16, 17, 24, 9, 937999)
 
In [17]: datetime.datetime.now()+datetime.timedelta(-3)#获取三天前时间
Out[17]: datetime.datetime(2018, 8, 13, 17, 25, 30, 124544)
 
In [18]: datetime.datetime.now()+datetime.timedelta(3)#获取三天后时间
Out[18]: datetime.datetime(2018, 8, 19, 17, 25, 37, 227889)
 
In [19]: datetime.datetime.now()+datetime.timedelta(hours=-3)#获取三小时后时间
Out[19]: datetime.datetime(2018, 8, 16, 14, 25, 58, 693782)

3.4.2 random模块

该模块是用来获取随机数的

In [1]: import random
 
In [2]: random.random()#获取0到1之间的随机浮点数,不包括1
Out[2]: 0.677995084773992
 
In [3]: random.randint(1,7)#获取1到7之间随机整数包括1和7
Out[3]: 5
 
In [4]: random.randrange(0,10,2)#从[0,2,4,6,8]获取一个数
Out[4]: 4
 
In [5]: random.choice(['Tuple','List','Dict'])#从序列中获取一个随机元素,序列可以是字符串
Out[5]: 'List'
 
In [6]: random.sample('abcdefg12345678',3)#多个字符中选取特定数据的字符
Out[6]: ['2', 'b', 'g']
 
In [7]: random.uniform(1,10)#从1到10之间随机取浮点数
Out[7]: 1.1508823971161368
 
In [10]: items=[1,2,3,4,5]
In [11]: random.shuffle(items)#打乱items里的顺序
In [12]: print(items)
[1, 2, 3, 4, 5]
In [13]: random.shuffle(items)
In [14]: print(items)
[3, 1, 4, 5, 2]

3.4.3 os模块

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

In [1]: import os

In [2]: os.getcwd()#获取当前工作目录
Out[2]: 'C:\\Users\\xhm'

In [3]: os.chdir(r'E:\API')#切换目录
In [4]: os.getcwd()
Out[4]: 'E:\\API'
    
In [5]: os.curdir#返回当前目录
Out[5]: '.'

In [6]: os.pardir#返回当前目录的父目录
Out[6]: '..'
    
In [9]: os.makedirs(r'E:\a\b\c')#递归创建目录

In [10]: os.removedirs(r'E:\a\b\c')#若目录为空,则删除,并递归到上一级目录,若也为空,递归删除 

In [11]: os.mkdir(r'E:\a')#生成单级目录
    
In [12]: os.rmdir(r'E:\a')#删除单级目录,若目录不为空则无法删除
    
In [13]: os.listdir('.')#列出当前目录下的所有文件和子目录
Out[13]: ['android', 'Java', 'python']   
  
In [14]: os.remove()#删除一个文件

In [15]: os.rename('oldname','newname')#重命名文件或目录

In [16]: os.stat(r'E:\API')#获取文件或目录一些信息
Out[16]: os.stat_result(st_mode=16895, st_ino=7881299347900100, st_dev=746907, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1534483928, st_mtime=1517730555, st_ctime=1517315399)

In [17]: os.sep#获取当前系统特定的路径分割符,win为\\,linux下为/
Out[17]: '\\'

In [18]: os.linesep#获取当前平台使用的行终止符,win下\r\n,linux下为\n
Out[18]: '\r\n'

In [16]: os.environ#获取当前系统环境变量,也就是path

In [17]: os.pathsep#获取当前系统路径(path)分割符,win是;linux是:
Out[17]: ';'

In [19]: os.name#获取当前使用的是什么系统
Out[19]: 'nt'

In [20]: os.system('dir')#执行系统命令
 驱动器 E 中的卷没有标签。
 卷的序列号是 000B-659B
 E:\API 的目录
2018/02/04  15:49    <DIR>          .
2018/02/04  15:49    <DIR>          ..
2018/02/04  16:09    <DIR>          android
2018/01/30  20:59    <DIR>          Java
2018/02/02  14:45    <DIR>          python
               0 个文件              0 字节
               5 个目录 214,796,689,408 可用字节
Out[20]: 0    

In [21]: os.path.abspath(path)#获取一个文件的绝对路径

In [22]: os.path.split(r'E:\a\b\c\a.txt')#将path分割成目录和文件名
Out[22]: ('E:\\a\\b\\c', 'a.txt')   

In [24]: os.path.dirname(r'E:\a\b\c\a.txt')#获取目录
Out[24]: 'E:\\a\\b\\c'

In [25]: os.path.basename(r'E:\a\b\c\a.txt')#获取文件名
Out[25]: 'a.txt'

In [28]: os.path.exists(r'E:')#判断路径是否存在
Out[28]: True
    
In [29]: os.path.isabs(r'E:\API')#判断是否是绝对路径
Out[29]: True

In [30]: os.path.isfile(path)#判断是否是文件

In [30]: os.path.isdir(path)#判断是否是目录
    
In [31]: os.path.join(r'E:',r'\a',r'\a.txt')#将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
Out[31]: 'E:\\a.txt'

In [32]: os.path.getatime(path)#返回path所指向的文件或者目录的最后存取时间
In [33]: os.path.getmtime(path)#返回path所指向的文件或者目录的最后修改时间

3.4.4 sys模块

sys.argv #获取命令行参数,返回一个列表,第一个元素是程序本身路径
sys.exit(n) #退出程序,正常退出时exit(0)
sys.version #获取Python版本
sys.path #获取模块的搜索路径
sys.platform #获取操作系统版本名称

3.4.5 shutil模块

该模块是用来拷贝文件的

import shutil      
shutil.copyfile('a.txt','b.txt')#将a.txt文件内容复制到b.txt里,仅拷贝文件
shutil.copymode('a.txt','b.txt')#仅拷贝权限。内容、组、用户均不变
shutil.copy('a.txt','b.txt')#拷贝文件和权限
shutil.copy2('a.txt','b.txt')#拷贝文件和信息包括权限
shutil.copystat('a.txt','b.txt')#拷贝文件信息
shutil.copytree('a','b')#递归拷贝
shutil.rmtree('b')#递归删除
shutil.move(path1,path2)#移动文件
shutil.make_archive(path,format,root_dir,···)#压缩文件
#format='zip'、'tar'、'bztar'、'gztar',root_dir要压缩文件夹路径

3.4.6 shelve模块

该模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久任何pickle可支持的python数据格式

import shelve
d=shelve.open('a')
info={'name':"xxx",'age':18}
mes=[1,2,3,4]
d['info']=info#持久化字典
d['mes']=mes#持久化列表
d.get('info')#获取信息

3.4.7 xml模块

xml创建

import xml.etree.ElementTree as ET

def main():
	s={}
	new_xml = ET.Element("personinfolist")#创建根节点
	personinfo = ET.SubElement(new_xml, "personinfo", attrib={"sex": "男"})
	name = ET.SubElement(personinfo, "name")
	name.text = "张三"
	age = ET.SubElement(personinfo, "age")
	age.text = '56'
	personinfo2 = ET.SubElement(new_xml, "personinfo", attrib={"sex": "小红"})
	name = ET.SubElement(personinfo2, "name")
	name.text = "小红"
	age = ET.SubElement(personinfo2, "age")
	age.text = '19'

	et = ET.ElementTree(new_xml)  # 生成文档对象
	et.write("person_info.xml", encoding="utf-8", xml_declaration=True)
	ET.dump(new_xml)  # 打印生成的格式

if __name__ == "__main__":
	main()
<?xml version='1.0' encoding='utf-8'?>
<personinfolist>
    <personinfo sex="">
        <name>小明</name>
        <age >56</age>
    </personinfo>
    <personinfo sex="">
        <name>小红</name>
        <age>19</age>
    </personinfo>
</personinfolist>

遍历xml文档

import xml.etree.ElementTree as ET

def main():
	tree=ET.parse('person_info.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,i.attrib)
if __name__ == "__main__":
	main()
    
'''
结果:
personinfolist
personinfo {'sex': '男'}
name 小明 {}
age 56 {}
personinfo {'sex': '女'}
name 小红 {}
age 19 {}


'''

3.4.8 configparser模块

该模块用于生成和修改常见配置文档

生成一个配置文件

import configparser #ConfigParser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
                     'Compression': 'yes',
                     'CompressionLevel': '9'}
config['topsecret.server.com'] = {}
config['topsecret.server.com']['Host Port'] = '50022'  # mutates the parser
config['topsecret.server.com']['ForwardX11'] = 'no'  # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('a.ini', 'w') as configfile:
    config.write(configfile)
    
    '''
    结果为:
    
    [DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[topsecret.server.com]
host port = 50022
forwardx11 = no
    
    '''

读取配置文件

import configparser
conf = configparser.ConfigParser()
conf.read("a.ini")
print(conf.defaults())
print(conf['bitbucket.org']['user'])
#print(conf.sections())
sec = conf.remove_section('bitbucket.org')
conf.write(open('example.ini', "w"))

3.4.9 hashlib模块和hmac模块

这两个模块用于加密相关的操作

In [1]: import hashlib

In [2]: m=hashlib.md5()

In [3]: m.update(b'Hello')

In [4]: m.hexdigest()
Out[4]: '8b1a9953c4611296a827abf8c47804d7'
In [5]: s=hashlib.sha512()

In [6]: s.update(b'Hello')

In [7]: s.hexdigest()
Out[7]: '3615f80c9d293ed7402687f94b22d58e529b8cc7916f8fac7fddf7fbd5af4cf777d3d795a7a00a16bf7e7f3fb9561ee9baae480da9fe7a18769e71886b03f315'

hmac模块,它内部对我们创建key和内容进行处理再加密

In [1]: import hmac

In [2]: h=hmac.new(b'123456')

In [3]: h.update(b'Hello')

In [4]: h.hexdigest()
Out[4]: '8d8e945298c899a7eb03fede467121fe'

3.4.10 re模块

常用正则表达式符号:

  1. 字符串匹配:
  • .匹配除换行符以外的任意一个字符
  • \w 匹配一个字符或数字或下划线或汉字
  • \s匹配任意一个空白字符
  • \d匹配一个数字
  • \D匹配非数字
  • \b匹配单词的开始或结束
  • ^匹配字符串的开始
  • $匹配字符串的结束
  • []字符集[a-c]表示匹配a或b或c
  • |匹配左边或者右边字符
  • ()被括起来的表达式将作为分组
  1. 字符串次数匹配:
  • *匹配前一个字符0次或多次
  • +匹配前一个字符1次或多次
  • ?匹配前一个字符0次或1次
  • {n}匹配前一个字符n次
  • {n,}匹配前一个字符n次或更多次
  • {n,m}匹配前一个字符n到m次
  1. 特殊分组用法
  • (?P<name>)分组,除了原有的编号外再指定一个额外的别名
  • (?P=name)引用别名为<name>的分组匹配到的字符串
  • \<number>引用编号为<number>的分组匹配到字符串

这里需要强调一下反斜杠\的作用:

  • 反斜杠后边跟元字符去除特殊功能;(即将特殊字符转义成普通字符)
  • 反斜杠后边跟普通字符实现特殊功能;(即预定义字符)
  • 引用序号对应的字组所匹配的字符串。

match:从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None。

In [1]: import re

In [2]: pat='h\w+'#正则模型

In [3]: str='hello,abc123'#要匹配的字符串

In [4]: r=re.match(pat,str)

In [5]: print(r.group())
hello

In [6]: print(r.groups())
()

In [7]: print(r.groupdict())
{}

#分组
In [8]: pat='h(?P<name>\w+).*c(?P<age>\d+)'#设置分组名为name和age

In [9]: r=re.match(pat,str)

In [10]: print(r.group())
hello,abc123

In [11]: print(r.groups())
('ello', '123')

In [12]: print(r.groupdict())
{'name': 'ello', 'age': '123'}

search: 浏览整个字符串去匹配第一个,为匹配成功返回None,这里强调一下match方法是从开头去匹配。

In [1]: import re

In [2]: pat='h\w+'#正则模型

In [3]: str='hello,abc123'#要匹配的字符串

In [4]: r=re.search(pat,str)

In [5]: print(r.group())
hello

findall:获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中多个组,则以列表形式返回,且每一个匹配均是元组;空的匹配也会包含在结果中。

In [1]: import re

In [2]: pat='h\w+'#正则模型

In [3]: str='hello,abc123'#要匹配的字符串

In [4]: r=re.findall(pat,str)

In [5]: print(r)
['hello']

sub:替换匹配成功的指定位置的字符串

In [1]: import re

In [2]: pat='h\w+'#正则模型

In [3]: str='hello,abc123'#要匹配的字符串

In [4]: r=re.sub(pat,'abc',str,1)#将字符串hello替换成abc,1代表多个只替换一个,默认是全部替换

In [5]: print(r)
'abc,abc123'

split:根据正则匹配分割字符串

In [1]: import re

In [2]: pat='h\w+'#正则模型

In [3]: str='hello,abc123'#要匹配的字符串

In [4]: r=re.split(',',str,1)#分割一次,默认是多次

In [5]: print(r)
['hello','abc123']

没有更多推荐了,返回首页