python_模块

一、什么是模块?

  别人写好的功能放在一个py文件里

  一般有:内置模块,第三方模块,自定义模块

二、序列化模块

  序列:列表,元祖,字符串,bytes

  什么是序列化?

    把一个数据类型转化成字符串,bytes类型就是序列化

  为什么要序列化?

    当你需要把一个数据类型放在文件文件时

    当你需要把一个数据类型通过网络传输时

  1、json模块

import json
dic = {'name':'张三','age':18}
str_dic = json.dumps(dic,ensure_ascii=False)
print(str_dic)
str_dic1 = json.loads(str_dic)
print(str_dic1)

li = [1,3,'a','sad']
str_li = json.dumps(li)
str_li1 = json.loads(str_li)
print(str_li)
print(str_li1)

# 操作文件 ensure_ascii=False 中文转码
with open('json_file.txt','w',encoding='utf-8') as f:
    json.dump(dic,f)

with open('json_file.txt',encoding='utf-8') as f1:
    print(json.load(f1))
View Code
# 可以多次向文件dump? 多次load吗?
# 可以多次dump,但不能load
info = {'name':'qwe','age':14}
with open('json_file.txt','a',encoding='utf-8') as f:
    json.dump(info,f,ensure_ascii=False)
with open('json_file.txt','r',encoding='utf-8') as f:
    json.load(f)

def my_dumps(dic):
    with open('json_file.txt','a',encoding='utf-8') as f:
        str_dic = json.dumps(dic)
        f.write(str_dic+'\n')
dic = {'name':'ald','age':12}
# my_dumps(dic)

with open('json_file.txt','r',encoding='utf-8') as f:
    for line in f:
        dic = json.loads(line.strip())
        print(dic)
View Code

json格式化

# json格式化
import json
data = {'username':['小明','小黑'],'sex':'male','age':16}
data_json = json.dumps(data,ensure_ascii=False,indent=4,sort_keys=True,separators=(',',':'))
print(data_json)
View Code

json的优点:

    所有的语言都通用

  缺点:

    只支持非常少的数据类型

    对数据类型的约束很苛刻

      字典的key必须是字符串

      只支持 :数字,列表,字符串,字典

  2、pickle

import pickle
s1 = {'name':'wam',1:('a','b',3)}
s2 = pickle.dumps(s1)
print(s2)
s3 = pickle.loads(s2)
print(s3)

class Course:
    def __init__(self,name,price):
        self.name = name
        self.price = price
python = Course('python',19800)
c1 = pickle.dumps(python)
print(c1)
c2 = pickle.loads(c1)
print(c2.name,c2.price)
View Code
# pickle多次dump和多次load需要异常处理‘
import pickle
dic = {'name':'xm','age':13}
def my_dump(dic):
    with open('pickle_file.txt','ab') as f:
        pickle.dump(dic,f)
# my_dump(dic)

with open('pickle_file.txt','rb') as f1:
    while 1:
        try:
            print(pickle.load(f1))
        except EOFError:
            break
pickle操作文件必须以+b模式打开
在load的时候,如果这个要被load的内容所在的类不存在内存中,会报错
View Code

三、时间模块

import time
print(time.time()) #当前时间戳时间,浮点数为单位
print(time.localtime())  #结构化时间
print(time.strftime('%y-%m-%d %H:%M:%S'))  #格式化时间

struct_time = time.localtime(3000000000)
fmt_time = time.strftime('%Y-%m-%d %H:%M:%S',struct_time)
print(fmt_time)

fmt_time = time.strftime('%Y-%m-1')
struc_time = time.strptime(fmt_time,'%Y-%m-%d')
timestamp = time.mktime(struc_time)
print(timestamp)
View Code

四、sys模块

sys模块是与python解释器交互的一个模块
print(sys.path)
一个模快能否被导入,就看这个模块所在的目录在不在sys.path中
内置模块和第三方扩展模块都不需要我们处理,sys.path可以直接访问
自定义模块的导入工作,需要自己手动的修改sys.path

print(sys.argv)
执行脚本时带的参数会存放在sys.argv列表中
print(sys.modules[__name__])
print(sys.version) #获取python解释程序的版本信息
print(sys.platform) #返回操作系统平台名称
View Code

五、os模块

import os
os模块是与操作系统交互的一个接口
os.mkdir('packge') #生成单级目录 相当于shell中mkdir dirname
os.makedirs('packge/app') #可生成多层递归目录

os.rmdir('packge') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.removedirs('packge/app') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推

os.remove('1.txt') #删除一个文件
os.rename('packge/112','packge/app') #重命名文件/目录
print(os.stat('F:\Demo\模块与包')) #获取文件,目录信息
st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。

print(os.listdir())  #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印

os.path
print(os.path.abspath('app')) #返回path规范化的绝对路径
print(os.path.split(r'F:\Demo\模块与包\01_json模块.py')) #将path分割成目录和文件名以元组返回
print(os.path.dirname(r'F:\Demo\模块与包\08_os模块.py'))
#返回path的目录。其实就是os.path.split(path)的第一个元素
print(os.path.basename(r'F:\Demo\模块与包\08_os模块.py'))
返回path最后的文件名。如果path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
print(os.path.exists(r'F:\Demo\模块与包\08_os模块.py')) #如果path存在,返回True;如果path不存在,返回False
print(os.path.isabs(r'F:\Demo\模块与包\08_os模块.py')) #如果path是绝对路径,返回True
print(os.path.isfile(r'F:\Demo\模块与包\08_os模块.py')) #如果path是一个存在的文件,返回True。否则返回False
print(os.path.isdir(r'F:\Demo\模块与包')) #如果path是一个存在的目录,则返回True。否则返回False
print(os.path.join('/app/','lib/','script')) 合并目录
print(os.path.getatime(r'F:\Demo\模块与包\08_os模块.py')) #返回path所指向的文件或者目录的最后访问时间
print(os.path.getmtime(r'F:\Demo\模块与包\08_os模块.py')) #返回path所指向的文件或者目录的最后修改时间
print(os.path.getsize(r'F:\Demo\模块与包\08_os模块.py')) # 返回path的大小

os.system('dir') #运行shell命令,直接显示
print(os.popen('dir').read()) #运行shell命令,获取执行结果
print(os.getcwd()) #获取当前工作目录,即当前python脚本工作的目录路径
os.chdir(r'F:\Demo\模块与包') #改变当前脚本工作目录;相当于shell下cd
print(os.getcwd())
View Code

六、collections模块

# collections模块
# 根据基础数据类型又做了一些扩展
# 有序字典
# Counter 计数器
# 默认字典
# 可命名元祖
# 双端队列

from collections import Iterable
from collections import Iterator

dic = {'name':'zs'}
print(isinstance(dic,Iterable)) #可迭代对象
print(isinstance(dic,Iterator)) #迭代器

dic = dict.fromkeys('abc',('a',1))
print(dic)

dic = dict([(1,2),('a',3)])
print(dic)

# 有序字典
from collections import OrderedDict
dd = OrderedDict([(1,2),('a',3)])
for k in dd:
    print(k,dd[k])
print(dd)

# 带有默认值的字典
from collections import defaultdict
d = defaultdict(dict)
d['b'] = 123
print(d['a'],d)

d = {}
print(d['a'])

func = lambda :'default'
d = defaultdict(func)
print(d['a'])

# 可命名元组
from collections import namedtuple
birth = namedtuple('Struct_time',['year','month','day'])
b1 = birth(2018,9,5)
print(b1,type(b1))
print(b1.year)
print(b1.month)
print(b1.day)

class A:
    pass
a = A()
print(type(A))
print(type(a))
# 可命名元组非常类似一个只有属性没有方法的类
# ['year','month','day']是对象属性名
# Struct_time是类 的名字
# 这个类最大的特点就是一旦实例化 不能修改属性的值

# 双端队列
from collections import deque
l1 = [1,3,4]
qu = deque(l1)
qu.append('a')
qu.append('b')
qu.appendleft(0)
qu.pop()
qu.popleft()
print(qu)
View Code

七、hashlib模块

  主要用于登陆验证和文件的一致性校验

  常用的算法有md5,sha等

  算法是不可逆的

  不同的字符串通过这个算法计算得到的密文始终是不同的

  相同的算法,相同的字符串。获得密文始终是相同的。不同的语言,不同的环境(操作系统、版本、时间)

  md5得到的是一组32位由16进制的字符串,sha得到的是一组40位由16进制的字符串

  sha算法相比md5算法更复杂,计算时间越长,安全性更高

  

  动态加盐

def get_md5(name,pw):
    obj_md5 = hashlib.md5(name.encode('utf-8'))
    obj_md5.update(pw.encode('utf-8'))
    return obj_md5.hexdigest()

def login():
    name = input('<<<name:').strip()
    pw = input('<<<pw:').strip()
    with open('info.txt',encoding='utf-8') as f:
        for line in f:
            u_name,u_pw = line.strip().split('|')
            if name == u_name and u_pw == get_md5(name,pw):
                print('登陆成功')
                return
View Code

    文件的一致性校验

import os
import hashlib
def get_file_md5(file_path,buffer=1024):
    obj_md5 = hashlib.md5()
    file_size = os.path.getsize(file_path)
    with open(file_path,'rb') as f:
        while file_size:
            content = f.read(buffer)
            file_size -= len(content)
            obj_md5.update(content)
    return obj_md5.hexdigest()
View Code

八、configparser模块

  配置文件目录

import configparser

config = configparser.ConfigParser()

config["DEFAULT"] = {'ServerAliveInterval': '45',
                      'Compression': 'yes',
                     'CompressionLevel': '9',
                     'ForwardX11':'yes'
                     }

config['bitbucket.org'] = {'User':'hg'}

config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'}

with open('example.ini', 'w') as configfile:

   config.write(configfile)

查找文件
import configparser
config = configparser.ConfigParser()

print(config.sections()) #[]
config.read('example.ini')
print(config.sections()) #['bitbucket.org', 'topsecret.server.com']

print('bitbucket.com' in config) #False
print('bitbucket.org' in config) #True

print(config['bitbucket.org']['user'])
print(config['topsecret.server.com']['Host Port'])

print(config['bitbucket.org'])  #<Section: bitbucket.org>

for key in config['bitbucket.org']: # 注意,有default会默认default的键
    print(key)

print(config.options('bitbucket.org')) # 同for循环,找到'bitbucket.org'下所有键

print(config.items('bitbucket.org'))  # #找到'bitbucket.org'下所有键值对

print(config.get('topsecret.server.com','CompressionLevel')) #get方法Section下的key对应的value

增删改操作
import configparser
config = configparser.ConfigParser()
config.read('example.ini')

config.add_section('path_info')

config.remove_section('bitbucket.org')
config.remove_option('topsecret.server.com','ForwardX11')
print(config.sections())
# print(config.items('topsecret.server.com'))

config.set('path_info','admin','user/login')
config.set('topsecret.server.com','k1','xxx')

config.write(open('new.ini','w'))
View Code 

九、日志模块

import logging
logging.basicConfig(level=logging.DEBUG)  #更改显示级别,默认是warning
logging.debug('the debug...') #计算或者工作的细节
logging.info('the info...')   #记录用户的信息,增删改操作
logging.warning('the warning...')  #警告操作
logging.error('the error...')   #错误操作
logging.critical('the critical...') #批判的,直接导致程序出错退出的

# 简单配置
logging.basicConfig(level=logging.INFO,format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',\
                     # datefmt='%c',
                     filename='test.log')
logging.debug('the debug...')
logging.info('the info...')
logging.warning('the warning...')
logging.error('the error...')
logging.critical('the critical...')

# 对象的配置
# 先创建一个log对象 logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# 创建一个控制文件输出的操作文件符
fh = logging.FileHandler('my.log',encoding='utf-8')
# 创建一个控制屏幕输出的屏幕操作符
sh = logging.StreamHandler()
sh.setLevel(logging.WARNING)

# 创建格式
fmt = logging.Formatter('%(asctime)s %(name)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
smt = logging.Formatter('%(asctime)s [line:%(lineno)d] %(levelname)s %(message)s')

# 文件操作符绑定一个格式
fh.setFormatter(fmt)
# 屏幕操作符绑定一个格式
sh.setFormatter(smt)

# logger对象来绑定:文件操作符,屏幕操作符
logger.addHandler(fh)
logger.addHandler(sh)

logging.debug('the debug...')
logging.info('用户信息...')
logging.warning('the warning...')
logging.error('the error')
logging.critical('the critical...')
View Code

十、模块和包

# 在import模块发生了?
'''
1、寻找模块
2、如果找到了这个模块,就开辟一个空间,然后执行这个模块
3、把这个模块中的名字都收录到这个新开辟的空间中
4、创建一个变量来引用这个模块的空间
'''

'''
1、模块不会重复被导入
2、模块与文件的内存空间始终是相互隔离的
3、模块的名字必须是符合变量的命名规范的
'''

# 模块的导入与修改
import time
from my_module import *
print(name)
time.sleep(10)
from my_module import *
print(name)

from importlib import reload
import time
import my_module
print(my_module.name)
time.sleep(10)
reload(my_module)
print(my_module.name)

#pyc文件、pyi文件
#pyc只能提高程序的启动效率并不能提高程序的执行效率
#模块不能循环引用

import my_module
print(dir(my_module))  #可以获取这个模块中所有的名字

__all__ 跟import *搭配
__all__['name','fun']

#导入包的两种方式
#绝对导入,相对导入
#单独导入包名称时不会导入包中所有包含的所有子模块
View Code

十一 、re模块

#什么是正则表达式? 只和字符串打交道
#是一种规则 来约束字符串的规则

# 字符组  是元字符中的一个
# 在字符组中所有的字符都可以匹配任意一个字符位置上能出现的内容
# 如果在字符串中有任意一个字符是字符组中的内容,那么就是匹配上的项
# [0-9]
# [a-z]
# [A-Z]
# ascii编码小的值 指向一个大的值
# [0-9a-zA-Z]
# [1-9][0-9]

# \d表示匹配一个数字 [0-9]

# 元字符
# \w word \d digit \s space \n next \t tab \W \D \S

# 元字符
# \w \d \s \W \D \S \n \t  匹配特殊的字符
# ^ $ \b  # 匹配边界
# [] [^]  # 字符组相关的
# |       # 或
# ()      # 分组
# .       # 匹配除了换行符之外的任意字符

# 写一个正则规则匹配一个手机号码

# 量词
# ?+ * {n} {n,} {n,m}
# \d+整数
# \d+\.\d+  小数
# \d+\.\d+|\d+ 整数或者小数
# \d+(\.\d+)?

# 贪婪匹配  : 正则会尽量多的帮我们匹配
    # 默认贪婪 回溯算法
# 非贪婪匹配 :会尽量少为我们匹配
    # 量词?表示非贪婪 惰性匹配
    # .*?x  表示匹配任意长度任意字符遇到一个x就立即停止

# 元字符
# 元字符 量词
# 元字符 量词 ? 在量词的范围内尽量少的匹配这个元字符
# 分组   对某些固定的内容做量词约束
# 或     把长的放前面

# 转义符
# pattern = r'\\n'
# s = r'\n'

import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret)
ret.remove('')
print(ret)

findall
res = re.findall('\d+','ss12sd234')
print(res)
# 返回值 是一个列表 所有匹配到的项

res = re.search('\d+','ss12sd234')
print(res)
print(res.group())
# 返回值 : 返回一个SRE_Match对象
#           通过group去取值
#           且只包含第一个匹配到的值

# findall的特点  优先显示分组中的内容
ret = re.findall('www\.(?:baidu|taobao)\.(?:com)','www.baidu.com')
print(ret)

# search可以通过参数查看指定分组
ret = re.search('www\.(baidu|taobao)\.(com)','www.baidu.com')
if ret:
    print(ret.group())
    print(ret.group(1))
    print(ret.group(2))

# match 同search 不过紧在字符串开始处匹配
ret = re.match('a','aac acd').group()
print(ret)

# split  先按a分割得到['','bcd'],再按b分割得到['','','cd']
ret = re.split('[ab]','abcd')
print(ret)

# sub 将数字替换成H,参数1表示只替换1次
ret = re.sub('\d','H','sa12ww12',1)
print(ret)

# subn 将数字替换成A,返回元祖(替换的结果,替换了多少次)
ret = re.subn('\d','A','sa12ww12')
print(ret)

# compile 将正则表达式编译成一个正则表达式对象,再调用其方法
obj = re.compile('\d{3}')
ret = obj.search('qwe123ew12')
print(ret.group())

# finditer 返回一个存放结果的迭代器
res = re.finditer('\d','3ee12cd34')
print(res)
for i in res:
    print(i.group())
print(next(res).group())
print(next(res).group())
print([i.group() for i in res])

# split的优先级
#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
res = re.split('\d+','wq1ew2we')
res = re.split('(\d+)','wq1ew2we')
print(res)

# 匹配标签
res = re.search('<(?P<name>\w+)>\w+</(?P=name)>','<h1>hdhs</h1>')
print(res.group('name'))
print(res.group())

res = re.search(r'<(\w+)>\w+</\1>','<h1>hdhs</h1>')
print(res.group(1))
View Code

十二、异常处理

# 异常处理
# 异常:在编译阶段没问题,在执行阶段才报错
# 语法错误:在程序执行之前就应该规避掉,不应该留到程序中进行异常处理
# 异常出现后,程序不会继续执行
try:
    print(name)
except NameError:
    print('name is not defind')

try:
    num = input('<<<')
    print(int(num))
except NameError:
    print('name is not defind')
except ValueError:
    print('invalid literal')

# Exception 可以捕获所有的异常
try:
    num = input('<<<')
    print(int(num))
except NameError:
    print('name is not defind')
except Exception as e:
    print(e)

# 没有异常,才执行else
try:
    num = input('<<<')
    print(int(num))
except ValueError:
    print('name is not defind')
else:
    print('执行成功')

# trr else不支持这种写法,语法错误
try:
    print(1)
else:
    print(2)

# finall 无论如何都执行
try:
    print(name)
finally:
    print('无论如何都执行')


# 自定义异常
class DiyError(BaseException):
    def __init__(self,message):
        self.message = message

    def __str__(self):
        return self.message

try:
    raise DiyError('类型错误')
except DiyError as e:
    print(e)

# 爬虫例子
import re
import json
from urllib.request import urlopen

def getPage(url):
    html = urlopen(url)
    return html.read().decode('utf-8')

def parsePage(s):
    '<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
    '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>', re.S

    com = re.compile( '<div class="item">.*?<em .*?>(?P<id>\d+).*?<span class="title">(?P<title>.*?)</span>'
    '.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>(?P<comment_num>.*?)评价</span>.*?'
    '<span class="inq">(?P<assess>.*?)</span>', re.S)

    ret = com.finditer(s)

    for i in ret:
        yield {
            'id':i.group('id'),
            'title':i.group('title'),
            'rating_num':i.group('rating_num'),
            'comment_num':i.group('comment_num'),
            'assess':i.group('assess')
        }

def main(num):
    url = 'https://movie.douban.com/top250?start=%s&filter=' % num
    reponse_html = getPage(url)
    ret = parsePage(reponse_html)
    # print(ret)

    f = open('move_info.txt','a',encoding='utf-8')
    for obj in ret:
        print(obj)
        # data = str(obj)
        data = json.dumps(obj,ensure_ascii=False)
        f.write(data+'\n')

count = 0
for n in range(25):
    main(count)
    count += 25
View Code

 

posted on 2018-09-03 21:31  旧巷子里的猫  阅读(208)  评论(0编辑  收藏  举报