模块
模块介绍
"""
什么是模块: 一系列功能的结合体
模块的三种来源:
1.内置的(python解释器自带)
2.第三方的(别人写的)
3.自定义的(自己写的)
模块的四种表现形式:
1.使用python编写的py文件(也就意味着py文件也可以称之为模块)
2.已被编译为共享库或DLL的C或C++扩展(了解)
3.把一系列模块组织到一起的文件夹(文件夹下有一个__init__.py文件,该文件夹称之为包,即一系列py文件的结合体)
4.使用C编写并连接到python解释器的内置模块
为什么要用模块:
1.用别人写好的模块(内置的,第三方的): 典型的拿来主义,极大的提高开发效率
2.用自己写的模块(自定义的): 当程序比较庞大时,项目不可能只在一个py文件中,当多个文件中都需要使用相同的方法时,可以将该公共的方法写到一个py文件中,其他文件中以模块的形式导过去直接调用即可
"""
模块导入
import 导入模块
"""
# run.py文件中导入md.py
import md
运行run.py文件首先会创建一个run.py的名称空间
首次导入模块(md.py)(******)
1.执行md.py文件
2.运行md.py文件中的代码将产生的名字与值存放到md.py名称空间中
3.在执行文件(run.py)中产生一个指向md.py名称空间的名字md
多次导入不会再执行模块文件,会用第一次导入的成果(******)
使用import导入模块,访问模块的名称空间中的名字: 模块名.名字,不加模块名前缀则会报错
只有当几个模块有相同部分或者属于用一个模块,才可以导入时写在同一行,import os,time,md
当几个模块没有联系的情况下,应分多次导入
import os
import time
import md
当模块名字比较复杂的情况下,可以给该模块名取别名
import testttttt as t
"""
from...import...
"""
# run1.py文件中导入md1.py
from md1 import money
会先创建run1.py的名称空间
首次导入md1.py模块
1.运行md1.py
2.将产生的名字存放到md1.py名称空间中
3.拿到指向模块md1.py名称空间中名字money
多次导入不会再执行模块文件,会用第一次导入的成果
# from md1 import *
在md1.py尾部加个__all__ = ['money','read1','read2'],不写change,则导入的时候拿不到拿不到,不写默认所有名字
from...import...句式缺点:
1.访问模块中的名字不需要加模块名前缀,加了会报错
2.访问模块中的名字可能会与当前执行文件中的名字冲突
补充
__all__可以指定当所在py文件被当做模块导入的时候,可以限制导入者能够拿到的名字个数,不写默认所有名字
from md1 import * # 一次性将md1模块中的__all__中的所以名字导入过来,不推荐使用,并且你根本不知道到底有哪些名字可以用
"""
解决循环导入问题
print ('正在导入m1' )
from m2 import y
x = 'm1'
print ('正在导入m1' )
x = 'm1'
from m2 import y
print ('正在导入m1' )
def f1 ():
from m2 import y,f2
print ('m1.f1>>>y: ' ,y)
f2()
x = 'm1'
print ('正在导入m2' )
from m1 import x
y = 'm2'
print ('正在导入m2' )
y = 'm2'
from m1 import x
print ('正在导入m2' )
def f2 ():
from m1 import x
print ('m2.f2>>>x: ' ,x)
y = 'm2'
import m1
m1.f1()
"""
如果出现循环导入问题,那么一定是你的程序设计的不合理,循环导入问题在程序设计阶段就应该避免
解决循环导入问题的方式:
1.方式1: 将循环导入句式写在文件最下方
2.方式2: 函数内导入模块
"""
模块的绝对导入与相对导入
"""
绝对导入: 依据执行文件所在的文件夹路径为准,绝对导入无论在执行文件中还是在被导入文件中都适用
相对导入
.代表当前路径
..代表上一级路径
...代表上上一级路径
注意:
相对导入不能在执行文件中使用,只能在被导入的模块中使用
使用相对导入,就不需要考虑执行文件到底是谁,只需要知道模块与模块之间路径关系
"""
__name__用法
print (__name__)
if __name__ == '__main__' :
index1()
模块查找顺序
"""
模块的查找顺序
1.内存
2.内置
3.sys.path(环境变量): 是一个动态变化的大列表,里面放了一堆文件路径,第一个路径永远是执行文件所在的文件夹
import sys
print(sys.path) # ['E: \\python学习\\python视频教程\\day14\\代码\\day14\\07 模块查找顺序',...]
注意: py文件名不应该与模块名(内置的,第三方的)冲突
"""
from dir1.dir import md
import sys
sys.path.append(r'E: \\python学习\\python视频教程\\day14\\代码\\day14\\07 模块的查找顺序\\dir1' )
print (sys.path)
from dir import md
包
"""
什么是包?
一系列模块文件的结合体,表示形式就是一个文件夹
该文件夹内通常会有一个__init__.py文件
包的本质还是模块
首次导入包:
1.先创建执行文件的名称空间
2.创建包下面的__init__.py文件的名称空间
3.执行包下面的__init__.py文件中的代码,将产生的名字放在包下面的__init__.py文件的名称空间中
4.在执行文件中拿到一个指向包下面的__init__.py文件的名称空间的名字
在导入语句中,.号的左边肯定是包(文件夹)
作为包的设计者来说:
1.当模块的功能特别多的情况下,应该分文件管理
2.模块之间可以使用相对导入(包里面的文件都应该是被导入的模块)
站在包的开发者,如果使用相对路径来管理的自己的模块,那么只需要以包的路径为基准依次导入模块
站在包的使用者,必须将包所在的文件夹路径添加到system path中(******)
python2如果要导入包,包下面必须要有__init__.py文件
python3如果要导入包,包下面没有__init__.py文件也不会报错
包导入示例见day17
"""
"""
目录结构:
p目录
__init__.py
m1.py
m2.py
dir目录
__init__.py
m3.py
start.py
"""
def f1 ():
print ("from m1 f1" )
def f2 ():
print ('from m2 f2' )
def f3 ():
print ('from m3 f3' )
from .m3 import f3
from .m1 import f1
from .m2 import f2
from .dir import f3
from p import f1
from p import f2
from p import f3
f1()
f2()
f3()
"""
from m1 f1
from m2 f2
from m3 f3
"""
常用模块
re模块
正则表达式
"""
在python中使用正则表达式,就必须依赖于re模块
正则的应用场景:
1.爬虫
2.数据分析
"""
"""
[]
.
^
$
| 一定要将长的放在前面,如: abc|ab
[^]
*
+
?
{n}
{n+}
{n,m}
() 当多个正则符号需要重复多次或者当做一个整体进行其他操作,那么可以分组的形式
\ 转义符,如匹配字符'\d': \\d,配置'\\d': \\\\d
r 转义符(python独有),如匹配字符'\d': r'\\d'
\w 字母数字下划线
\s 任意空白符
\d 数字
\W 非字母数字下划线
\S 非任意空白符
\D 非数字
\n 换行符
\t 制表符
\b 一个单词的结尾,如l\b: 以l结尾的单词
通过在量词(* + ? {n} {n+} {n,m}等)后面加上?就可以将贪婪匹配变成非贪婪匹配(惰性匹配)
"""
re模块findall、search、match方法
"""
findall
re.findall('正则表达式','需匹配的字符串')
找出字符串中符合正则表达式的全部内容,返回的是一个列表
search
re.search('正则表达式','需匹配的字符串')
search不会直接返回匹配到的结果,而是返回一个对象,必须调用group才能看到匹配到的结果
search只会依据正则查一次,只要查到了结果,就不会再往后查找
当查找的结果不存在的情况下,调用group直接报错(因为不存在返回的是None,None没有group方法)
match
re.match('正则表达式','需匹配的字符串')
match不会直接返回匹配到的结果,而是返回一个对象,必须调用group才能看到匹配到的结果
match只会匹配字符串的开头部分
当字符串的开头不符合匹配规则的情况下,返回的也是None,调用group也会报错
"""
import re
res = re.findall('[a-z]+' ,'eva egon jason' )
print (res)
res = re.search('a' ,'eva egon jason' )
print (res)
print (res.group())
res1 = re.search('b' ,'eva egon jason' )
if res1:
print (res1.group())
res = re.match('eva' ,'eva egon jason' )
print (res)
print (res.group())
res = re.search('^[1-9](\d{14})(\d{2}[0-9x])?$' ,'110105199812067023' )
res1 = re.search('^[1-9](?P<password>\d{14})(?P<username>\d{2}[0-9x])?$' ,'110105199812067023' )
print (res.group())
print (res1.group('password' ))
print (res1.group(1 ))
print (res1.group('username' ))
print (res1.group(2 ))
ret1 = re.findall('www.(baidu|oldboy).com' , 'www.oldboy.com' )
ret2 = re.findall('www.(?: baidu|oldboy).com' , 'www.oldboy.com' )
print (ret1,ret2)
re模块其他方法
ret = re.split('[ab]' , 'abcd' )
print (ret)
ret1=re.split("\d+" ,"eva3egon4yuan" )
print (ret1)
ret2=re.split("(\d+)" ,"eva3egon4yuan" )
print (ret2)
ret = re.sub('\d' , 'H' , 'eva3egon4yuan4' , 1 )
print (ret)
re.sub('正则表达式' ,'新的内容' ,'待替换的字符串' ,要替换的个数)
ret = re.subn('\d' , 'H' , 'eva3egon4yuan4' )
ret1 = re.subn('\d' , 'H' , 'eva3egon4yuan4' ,1 )
print (ret)
print (ret1)
obj = re.compile ('\d{3}' )
ret = obj.search('12a345bb6789ccc' )
res1 = obj.findall('12a345bb6789ccc' )
print (ret.group())
print (res1)
ret = re.finditer('\d' , 'jll98' )
print (ret)
print (ret.__next__().group())
print (next (ret).group())
print (next (ret).group())
print ([i.group() for i in ret])
正则在爬虫中的应用
"""
拿到豆瓣电影TOP250的电影的排名、电影名、评分、评价人数
{'id': '1', 'title': '肖申克的救赎', 'rating_num': '9.6', 'comment_num': '1489907人'}
一共十页,每页25个电影:
第一页url: https: //movie.douban.com/top250?start=0&filter=
第一页url: https: //movie.douban.com/top250?start=25&filter=
第一页url: https: //movie.douban.com/top250?start=50&filter=
第一页url: https: //movie.douban.com/top250?start=75&filter=
<li>
<div class="item">
<div class="pic">
<em class="">1</em>
<a href="https: //movie.douban.com/subject/1292052/">
<img width="100" alt="肖申克的救赎" src="https: //img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
</a>
</div>
<div class="info">
<div class="hd">
<a href="https: //movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港) / 刺激1995(台)</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p class="">
导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...<br>
1994 / 美国 / 犯罪 剧情
</p>
<div class="star">
<span class="rating5-t"></span>
<span class="rating_num" property="v: average">9.7</span>
<span property="v: best" content="10.0"></span>
<span>2582438人评价</span>
</div>
<p class="quote">
<span class="inq">希望让人自由。</span>
</p>
</div>
</div>
</div>
</li>
"""
import re
import json
from urllib.request import urlopen
def getPage (url ):
response = urlopen(url)
return response.read().decode('utf-8' )
def parsePage (s ):
com = re.compile (
'<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)
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" ),
}
def main (num ):
url = 'https: //movie.douban.com/top250?start=%s&filter=' % num
response_html = getPage(url)
ret = parsePage(response_html)
print (ret)
f = open ("move_info7" , "a" , encoding="utf8" )
for obj in ret:
print (obj)
data = str (obj)
f.write(data + "\n" )
count = 0
for i in range (10 ):
main(count)
count += 25
collections模块
"""
基本数据类型:
整型
浮点型
字符串
列表
布尔
元组
字典
集合
conllections模块提供了几个额外的数据类型:
namedtuble 具名元组
deque 双端队列(queue 队列)
OrderedDict 有序字典
defaultdict 默认值字典
Counter 计数,统计字符串中每个字符出现的次数
"""
from collections import namedtuple
point = namedtuple('坐标' ,['x' ,'y' ,'z' ])
point1 = namedtuple('坐标' ,'x y z' )
p = point(1 ,2 ,5 )
p1 = point(1 ,2 ,5 )
print (p)
print (p1)
print (p.x)
print (p.y)
print (p.z)
import queue
q = queue.Queue()
q.put('first' )
q.put('second' )
q.put('third' )
print (q.get())
print (q.get())
print (q.get())
print (q.get())
"""
append 右追加
appendleft 左追加
pop 右取值
popleft 左取值
insert 特殊点: 双端队列可以根据索引在任意位置插值
队列不应该支持任意位置插值
只能在首尾插值(不能插队)
"""
from collections import deque
q = deque(['a' ,'b' ,'c' ])
q.append(1 )
q.appendleft(2 )
q.insert(1 ,'哈哈哈' )
print (q.pop())
print (q.popleft())
print (q.popleft())
from collections import OrderedDict
order_d = OrderedDict([('a' ,1 ),('b' ,2 ),('c' ,3 )])
print (order_d)
order_d1 = OrderedDict()
print (order_d1)
order_d1['x' ] = 1
order_d1['y' ] = 2
order_d1['z' ] = 3
print (order_d1)
from collections import defaultdict
values = [11 , 22 , 33 , 44 , 55 , 66 , 77 , 88 , 99 ]
my_dict = defaultdict(list )
for value in values:
if value>66 :
my_dict['k1' ].append(value)
else :
my_dict['k2' ].append(value)
print (my_dict)
my_dict1 = defaultdict(int )
print (my_dict1['xxx' ])
my_dict2 = defaultdict(bool )
print (my_dict2['kkk' ])
my_dict3 = defaultdict(tuple )
rint(my_dict3['mmm' ])
m collections import Counter
s = 'jll990108jll'
print (Counter(s
时间模块
time模块
"""
三种表现形式:
1.时间戳
2.格式化时间(用来展示给人看)
3.结构化时间
"""
import time
print (time.time())
print (time.strftime('%Y-%m-%d' ))
print (time.strftime('%Y-%m-%d %H: %M: %S' ))
print (time.strftime('%Y-%m-%d %X' ))
print (time.localtime())
res = time.localtime(time.time())
print (res)
print (time.mktime(res))
res1 = (time.strftime('%Y-%m-%d' ,time.localtime()))
print (time.strptime(res1,'%Y-%m-%d' ))
time.sleep(3 )
datetime模块
import datetime
print (datetime.date.today())
print (datetime.datetime.today())
res = datetime.date.today()
res1 = datetime.datetime.today()
res2 = res1.strftime('%Y-%m-%d %X' )
res3 = datetime.datetime.strftime(res2, '%Y-%m-%d %X' )
print (res1, type (res1))
print (res2, type (res2))
print (res3, type (res3))
print (res.year)
print (res.month)
print (res.day)
print (res.weekday())
print (res.isoweekday())
print (res1.year)
print (res1.month)
print (res1.day)
print (res1.weekday())
print (res1.isoweekday())
print (res1.hour)
print (res1.minute)
print (res1.second)
"""
(******)
日期对象 = 日期对象 +/- timedelta对象
timedelta对象 = 日期对象 +/- 日期对象
"""
current_t = datetime.date.today()
timetel_t = datetime.timedelta(days=7 )
print (current_t)
print (timetel_t)
print (current_t + timetel_t)
print (res)
print (current_t - res)
print (datetime.datetime.today())
print (datetime.datetime.now())
print (datetime.datetime.utcnow())
random模块
import random
print (random.randint(1 ,6 ))
print (random.random())
print (random.choice([1 ,2 ,3 ,4 ,5 ,6 ]))
res = [1 ,2 ,3 ,4 ,5 ,6 ]
random.shuffle(res)
print (res)
def get_code (n ):
code = ''
for i in range (n):
upper_str = chr (random.randint(65 ,90 ))
lower_str = chr (random.randint(97 ,122 ))
random_int = str (random.randint(0 ,9 ))
code += random.choice([upper_str,lower_str,random_int])
return code
print (get_code(6 ))
os模块
import os
"""
os.path.dirname(__file__) 脚本以完整路径被运行则返回该脚本所在完整路径(不包含文件名),脚本以相对路径被运行则返回空目录
os.path.abspath(__file__) 返回该脚本所在绝对路径(包含文件名)
os.path.join() 连接两个或更多的路径名组件
os.listdir() 将传入的文件夹下的所有文件展示出来
"""
BASE_DIR = os.path.dirname(__file__)
MOVIE_DIR = os.path.join(BASE_DIR,'老师们的作品' )
MOVIE_DIR = os.path.join(BASE_DIR,'老师们的作品' ,'优秀' )
movie_list = os.listdir(MOVIE_DIR)
while True :
for i,j in enumerate (movie_list,1 ):
print (i,j)
choice = input ('你想看谁的: ' ).strip()
if choice.isdigit():
choice = int (choice)
if choice in range (1 ,len (movie_list)+1 ):
target_file = movie_list[choice-1 ]
target_path = os.path.join(MOVIE_DIR,target_file)
with open (target_path,'r' ,encoding='utf-8' ) as f:
print (f.read())
"""
os.mkdir() 一级一级创建目录
os.makedirs() 一次创建多级创建目录
os.rmdir()
os.path.exists()
os.path.isfile()
os.path.isdir()
os.getcwd()
os.chdir()
os.path.getsize()
os.remove() 删文件
os.rename() 改文件名
"""
os.mkdir('tank老师精选' )
os.rmdir(r'E: \python学习\python视频教程\day16\代码\day16\tank老师精选' )
print (os.path.exists(r'E: \python学习\python视频教程\day16\代码\day16\老师们的作品' ))
print (os.path.exists(r'E: \python学习\python视频教程\day16\代码\day16\老师们的作品\tank老师.txt' ))
print (os.path.isfile(r'E: \python学习\python视频教程\day16\代码\day16\老师们的作品\tank老师.txt' ))
print (os.getcwd())
os.chdir(r'E: \python学习\python视频教程\day16\代码\day16\老师们的作品' )
print (os.getcwd())
print (os.path.getsize(r'E: \python学习\python视频教程\day16\代码\day16\老师们的作品\tank老师.txt' ))
sys模块
import sys
"""
sys.path: 是python搜索模块的路径集,是一个list,里面包含了已经添加到系统环境变量的路径
sys.path.append(PATH): 向sys.path中添加自己的引用模块搜索目录
print(sys.platform) 获取当前系统平台
print(sys.version) 获取python版本
print(sys.argv) 获取命令行参数,实现从程序外部向程序传递参数,是一个list,第一个元素是程序本身,随后才依次是外部给予的参数
"""
if len (sys.argv) <= 1 :
print ('请输入用户名和密码' )
else :
username = sys.argv[1 ]
password = sys.argv[2 ]
if username == 'jason' and password == '123' :
print ('欢迎使用' )
else :
print ('用户或密码错误,无法执行当前文件' )
"""
>python3 test.py jason 123
"""
class Person :
def __init__ (self,name ):
self.name = name
p = Person("jack" )
print (sys.getsizeof(p))
序列化模块
json模块
"""
写入文件的数据必须是字符串
基于网络传输的数据必须是二进制
序列化: 其他数据类型转成字符串
反序列化: 字符串转成其他数据类型
json模块:
所有语言都支持json格式
支持的数据类型很少: 整型、浮点型、字符串、列表、布尔、元组(转成列表)、字典
"""
"""
dumps: 序列化,将其他数据类型转成json格式的字符串(json格式的字符串是双引号)
loads: 反序列化,将json格式的字符串转换成其他数据类型
dump: 序列化并写入文件
load: 从文件取出并反序列化
"""
import json
d = {"name" : "jason" }
res = json.dumps(d)
print (res, type (res))
res1 = json.loads(res)
print (res1, type (res1))
d = {"name" : "jason" }
with open ('userinfo' ,'w' ,encoding='utf-8' ) as f:
json.dump(d,f)
with open ('userinfo' ,'r' ,encoding='utf-8' ) as f:
res = json.load(f)
print (res,type (res))
d = {"name" : "jason" }
with open ('userinfo' ,'w' ,encoding='utf-8' ) as f:
json_str = json.dumps(d)
json_str1 = json.dumps(d)
f.write('%s\n' %json_str)
f.write('%s\n' %json_str1)
with open ('userinfo' ,'r' ,encoding='utf-8' ) as f:
for line in f:
res = json.loads(line)
print (res,type (res))
t = (1 ,2 ,3 ,4 )
print (json.dumps(t))
d = {'name' : '朱志坚' }
print (json.dumps(d))
print (json.dumps(d, ensure_ascii=False ))
import json
from datetime import datetime,date
class MyJson (json.JSONEncoder):
def default (self, o ):
if isinstance (o,datetime):
return o.strftime('%Y-%m-%d %X' )
elif isinstance (o,date):
return o.strftime('%Y-%m-%d' )
else :
return super ().default(self,o)
res = {'c1' :datetime.today(),'c2' :date.today()}
print (json.dumps(res, cls=MyJson))
pickle模块
"""
pickle模块:
只支持python
python所有的数据类型都支持
pickle序列化的结果是一个二进制数据(bytes类型),用pickle操作文件时,文件的打开模式必须是b模式
"""
import pickle
d = {'name' : 'jason' }
res = pickle.dumps(d)
print (res,type (res))
res1 = pickle.loads(res)
print (res1,type (res1))
d = {'name' : 'jason' }
with open ('userinfo' ,'wb' ) as f:
pickle.dump(d,f)
with open ('userinfo_1' ,'rb' ) as f:
res = pickle.load(f)
print (res,type (res))
subprocess模块
"""
1.用户通过网络连接上了你的电脑
2.用户输入命令,基于网络发送给了你的电脑上某个程序
3.获取用户命令,利用subprocess执行用户命令
4.将执行结果基于网络发送给用户
实现了用户远程操作你的电脑
"""
while True :
cmd = input ('cmd>>>: ' ).strip()
import subprocess
obj = subprocess.Popen(cmd,shell=True ,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print ('正确命令返回的结果stdout' ,obj.stdout.read().decode('gbk' ))
print ('错误命令返回的提示信息stderr' ,obj.stderr.read().decode('gbk' ))
typing模块
"""
typing模块的作用:
1.类型检查,防止运行时出现参数和返回值类型不符合。
2.作为开发文档附加说明,方便使用者调用时传入和返回参数类型。
3.该模块加入后并不会影响程序的运行,不会报正式的错误,只有提醒。
注意: typing模块只有在python3.5以上的版本中才可以使用
"""
from typing import List , Tuple , Union
def test1 (name: str ,
age: int ,
balance: float ,
user_info: List ) -> Tuple [str , int , float , List ]:
print (name, age, balance, user_info)
return name, age, balance, user_info
res = test1('赵铁柱' , 18 , 18000.0 , ['a' , 'b' , 'c' ])
print (res)
"""
说明:
1.在传入参数时通过"参数名: 类型"的形式声明参数的类型;
2.返回结果通过"-> 结果类型"的形式声明结果的类型。
3.在调用的时候如果参数的类型不正确pycharm会有提醒,但不会影响程序的运行。
4.对于如list列表等,还可以规定得更加具体一些,如: "-> List[str]",规定返回的是列表,并且元素是字符串。
"""
"""
typing常用的类型:
1.int,long,float: 整型,长整形,浮点型;
2.bool,str: 布尔型,字符串类型;
3.List,Tuple,Dict,Set: 列表,元组,字典,集合;
4.Iterable,Iterator: 可迭代类型,迭代器类型;
5.Generator: 生成器类型;
"""
logging模块
logging基本使用
logging模块: 日志模块
import logging
logging.basicConfig(filename='access.log' ,
format ='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s' ,
datefmt='%Y-%m-%d %H: %M: %S %p' ,
level=10 )
logging.debug('debug日志' )
logging.info('info日志' )
logging.warning('warning日志' )
logging.error('error日志' )
logging.critical('critical日志' )
"""
1.logger对象: 产生日志
2.filter对象: 过滤日志(了解)
3.handler对象: 控制日志输出位置(文件/终端)
4.formater对象: 规定日志格式
"""
logger = logging.getLogger('转账记录' )
hd1 = logging.FileHandler('a1.log' ,encoding='utf-8' )
hd2 = logging.FileHandler('a2.log' ,encoding='utf-8' )
hd3 = logging.StreamHandler()
fm1 = logging.Formatter(
fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s' ,
datefmt='%Y-%m-%d %H: %M: %S %p' ,
)
fm2 = logging.Formatter(
fmt='%(asctime)s - %(name)s: %(message)s' ,
datefmt='%Y-%m-%d' ,
)
logger.addHandler(hd1)
logger.addHandler(hd2)
logger.addHandler(hd3)
hd1.setFormatter(fm1)
hd2.setFormatter(fm2)
hd3.setFormatter(fm1)
logger.setLevel(20 )
logger.debug('写了半天 好累啊' )
logging字典配置
import os
import logging.config
standard_format = '[%(asctime)s][%(threadName)s: %(thread)d][task_id: %(name)s][%(filename)s: %(lineno)d]' \
'[%(levelname)s][%(message)s]'
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s: %(lineno)d]%(message)s'
logfile_dir = os.path.dirname(__file__)
logfile_name = 'a3.log'
if not os.path.isdir(logfile_dir):
os.mkdir(logfile_dir)
logfile_path = os.path.join(logfile_dir, logfile_name)
LOGGING_DIC = {
'version' : 1 ,
'disable_existing_loggers' : False ,
'formatters' : {
'standard' : {
'format' : standard_format
},
'simple' : {
'format' : simple_format
},
},
'filters' : {},
'handlers' : {
'console' : {
'level' : 'DEBUG' ,
'class' : 'logging.StreamHandler' ,
'formatter' : 'simple'
},
'default' : {
'level' : 'DEBUG' ,
'class' : 'logging.handlers.RotatingFileHandler' ,
'formatter' : 'standard' ,
'filename' : logfile_path,
'maxBytes' : 1024 *1024 *5 ,
'backupCount' : 5 ,
'encoding' : 'utf-8' ,
},
},
'loggers' : {
'' : {
'handlers' : ['default' , 'console' ],
'level' : 'DEBUG' ,
'propagate' : True ,
},
},
}
logging.config.dictConfig(LOGGING_DIC)
logger1 = logging.getLogger('jll_log' )
logger1.debug('不要浮躁 努力就有收获' )
hashlib模块
"""
hashlib模块: 加密模块,加密的过程是无法解密的
1.不同的算法,使用方法是相同的
2.密文的长度越长,内部对应的算法越复杂,但是
1.时间消耗越长
2.占用空间更大
通常情况下使用md5算法,就足够了
hashlib模块应用场景:
1.密码的密文存储
2.校验文件内容是否一致
"""
import hashlib
md = hashlib.md5()
md.update(b'hello' )
print (md.hexdigest())
md = hashlib.md5()
md1 = hashlib.md5()
md.update(b'areyouok?' )
md1.update(b'are' )
md1.update(b'you' )
md1.update(b'ok?' )
print (md.hexdigest())
print (md1.hexdigest())
md = hashlib.md5()
md.update(b'oldboy.com' )
md.update(b'hello' )
print (md.hexdigest())
def get_md5 (data ):
md = hashlib.md5()
md.update('加盐' .encode('utf-8' ))
md.update(data.encode('utf-8' ))
return md.hexdigest()
password = input ('password>>>: ' )
res = get_md5(password)
print (res)
openpyxl模块
"""
03版本之前excel文件的后缀名叫xls
03版本之后excel文件的后缀名叫xlsx
之前用的模块:
xlwd 写excel
xlrt 读excel
xlwd和xlrt既支持03版本之前的excel文件也支持03版本之后的excel文件
openpyxl只支持03版本之后的xlsx
"""
from openpyxl import Workbook
wb = Workbook()
wb1 = wb.create_sheet('index' , 0 )
wb2 = wb.create_sheet('index1' )
wb1.title = 'login'
wb1['A3' ] = 666
wb1['A4' ] = 444
wb1['A5' ] = '=sum(A3: A4)'
wb1.cell(row=6 ,column=3 ,value=888 )
wb2.append(['username' ,'age' ,'hobby' ])
wb2.append(['jason' ,18 ,'study' ])
wb2.append(['egon' ,28 ,])
wb2.append(['nick' ,'' ,'秃头' ])
wb.save('test.xlsx' )
from openpyxl import load_workbook
wb = load_workbook('test.xlsx' ,read_only=True ,data_only=True )
print (wb.sheetnames)
print (wb['login' ]['A3' ].value)
print (wb['login' ]['A5' ].value)
res = wb['login' ]
ge1 = res.rows
print (ge1)
for i in ge1:
for j in i:
print (j.value)
copy模块深浅拷贝
l = [1 ,2 ,[1 ,2 ]]
l1 = copy.copy(l)
print (id (l),id (l1))
l[0 ] = 222
print (l,l1)
l[2 ].append(666 )
print (l,l1)
l = [1 ,2 ,[1 ,2 ]]
l1 = copy.deepcopy(l)
l[2 ].append(666 )
print (l,l1)
uuid模块
import uuid
import hashlib
print (uuid.uuid4())
print (type (uuid.uuid4()))
md5 = hashlib.md5()
md5.update(str (uuid.uuid4()).encode('utf-8' ))
print (md5.hexdigest())
pymysql模块
pymysql基本使用
import pymysql
conn = pymysql.connect(
host='localhost' ,
port=3306 ,
user='root' ,
password='123456' ,
database='db1' ,
charset='utf8' ,
autocommit = True )
cursor=conn.cursor(pymysql.cursors.DictCursor)
user = input ("user>>>:" ).strip()
pwd = input ("password>>>:" ).strip()
sql = 'select * from userinfo where name=%s and passwd=%s'
rows = cursor.execute(sql,(user,pwd))
print (rows)
if rows:
print (cursor.fetchone())
print (cursor.fetchall())
print (cursor.fetchmany(2 ))
cursor.scroll(2 ,'absolute' )
cursor.scroll(1 ,'relative' )
else :
print ('用户名或密码错误' )
cursor.close()
conn.close()
"""
sql注入问题:利用特殊符号(MySQL中的引号、注释--)巧妙的修改sql语句
解决方法:sql语句不要手动拼接,交给execute,execute能够识别sql语句中的%s并且过滤特殊符号,能完成sql语句的拼接
# 用户名错误(select * from userinfo where name = "jll" -- abcdefg)
username >>>: jll" -- abcdefg
# 用户名密码都错误(select * from userinfo where name = "xxx" or 1=1 -- abcdefg)
username >>>: xxx" or 1=1 --abcdefg
password >>>: xxx
"""
pymysql调用存储过程
import pymysql
conn = pymysql.connect(
host = '127.0.0.1' ,
port = 3306 ,
user = 'root' ,
password = '123' ,
database = 'day39' ,
charset = 'utf8' ,
autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.callproc('p1' ,(1 ,5 ,10 ))
print (cursor.fetchall())
cursor.execute('select @_p1_0' )
print (cursor.fetchall())
cursor.execute('select @_p1_1' )
print (cursor.fetchall())
cursor.execute('select @_p1_2' )
print (cursor.fetchall())
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!