7.常用模組
目錄
- 一、模組
- 二、random模組
- collections模組
- 三、hashlib模組
- 四、json模組
- 五、pickle模組
- 六、os模組
- 七、sys模組
- 八、time模組
- 九、datetime模組
- 十、logging模組
- 十一、functools模組
一、模組
import 模組名
'''
1、建立名為da17的名稱空間
2、執行此名稱空間的所有程式碼
3、通過da17.xx的方式引用
'''
模組的匯入
# sys.path.append(r'D:\code\acb ') # 使用的是絕對路徑 # 使用相對路徑找到位置 # print(__file__) # 當前的絕對路徑 # 使用os獲取一個路徑的父路徑 # print(os.path.dirname(__file__)+r'\acb') # sys.path.append(os.path.dirname(__file__)+ r'\acb') # 使用相對路徑匯入模組
相對匯入
- 一個點意味著引用的模組或包位於與當前位置相同的目錄中
- 兩個點意味著它在當前位置的父目錄中,也就是上層的目錄。
- 三個點意味著它在祖父母目錄中,
匯入包會執行某個下的__init__模組,一個py檔案中有相對匯入是不可以直接執行的。
from ... import * 和 import ...的區別
- from ... import *:匯入模組時,會跳過私有屬性
- import ...:通過引用可以訪問私有屬性
二、random模組
# random 隨機數 import random # random.random() # 獲取0.0-1.0之間的浮點數 # random.randint(a, b) # 獲取[a, b)範圍內的整數 # random.uniform(a, b) # 獲取[a,b)之間的浮點數 # random.shuffle(x) # 把引數指定的資料中的元素打亂,引數必須是一個可變的資料型別 # random.sample(x, k) # 從x中隨機抽取k個數據,組成一個列表返回
collections模組
collections 模組中的三個常用類
namedtuple():命名元組
defaultdict():預設值字典
Counter():計數器
namedtuple():命名元組
from collections import namedtuple Rectangle = namedtuple('Rectangle_class', ['length', 'width']) r = Rectangle(10, 5) print(r) # Rectangle_class(length=10, width=5) # 通過訪問元組的元素 print(r.length) print(r.width) print(type(r)) # 輸出<class '__main__.Rectangle_class'> # 通過索引的方式訪問元素 print(r[1]) # Counter:計數器 c = Counter('asdasdadwqeasd') print(c) print(c.most_common(3)) # 取前三
defaultict():設定預設值字典
from collections import defaultdict
d = defaultdict(int, name='An', age=12)
print(d['name'])
print(d['age'])
print(d['addr']) # {'addr':'0'} 也會別新增
print(d)
# 自定義函式充當第一個引數
# def func():
# return 'hello' # 最佳鍵的預設值
# d = defaultdict(func, ame='an', age=11)
# print(d['addr']) # hello
# print(d['tell']) # hello
# print(d) # defaultdict(<function func at 0x0000017F0EA54EE0>, {'ame': 'an', 'age': 11, 'addr': 'hello', 'tell': 'hello'})
Counter():計數器
from collections import Counter
c = Counter('asdasdadwqeasd')
print(c)
print(c.most_common(3)) # 取前三
三、hashlib模組
加密類
MD5 不可逆加密結果用於驗證,並非解密,
兩個資料的MD5相同,表示原文相同
MD5是最常見的摘要演算法,生成結果是128bit位元組,通常是一個32位的16進位制字串表示。另一種摘要演算法是SHA1,和呼叫MD5類似。SHA1的結果是160bit位元組,通常用40位的16進位制字串表示。還有SHA256和SHA512,他們更安全但是更慢。
'''
1、把一個大的資料,切分成不同的小塊,分別對不同的塊加密和直接對大塊加密結果一樣
2、單向不可逆
3、原始資料的小變化導致結果的大差異
'''
'''
1、獲取加密物件
2、使用update方法,可以呼叫多次
3、呼叫hexdigest()方法輸出加密後的md5
'''
import hashlib
# 獲取加密物件
m = hashlib.md5()
# 使用加密物件的update進行加密
m.update(b'asfnaj') # 傳入位元組型別引數
# m.update('中文'.encode('utf-8'))
res = m.hexdigest()
# print(res)
# 不同的加密演算法實質就是加密結果的長度不同
# 建立加密物件時,可以指定引數,稱為salt,把update的引數傳入hashlib.md5()中
# m = hashlib.md5(b'asfnaj')
# m.update()
# print(m.hexdigest())
# 多次對小塊加密,與小塊合成的大塊加密結果相同
# 登入註冊驗證
op = int(input('1、註冊2、登入3、退出'))
def get_md5(username, password):
m = hashlib.md5()
m.update(username.encode('utf-8'))
m.update(password.encode('utf-8'))
return m.hexdigest()
def register(username, password):
res = get_md5(username, password)
with open('login', mode='at')as f:
f.write(res + '\n')
def login(username, password):
res = get_md5(username,password)
with open('login', mode='rt',encoding='utf-8')as f:
for line in f:
if res == line.strip():
return True
else:
return False
if op == 1:
username = input('輸入使用者名稱')
password = input('輸入密碼')
register(username, password)
elif op == 2:
username = input('輸入使用者名稱')
password = input('輸入密碼')
login(username, password)
if res:
print('登入成功')
else:
print('登入失敗')
四、json模組
序列化和反序列化
物件(或變數)從記憶體變成可儲存或可傳輸的過程稱之為序列化
json
json模組是將滿足條件的資料結構轉化成特殊的字串,並且也可以反序列化還原回去。
序列化(serialization):結構化資料--->線性資料, 反序列化(deserialization)
線性資料:資料之間沒有應用關係
結構化資料:記憶體中
序列化過程:將記憶體中的資料轉換為位元組,用以儲存在檔案或者通過網路傳輸
# 元組序列化後變成列表
# print(json.dumps((1, 3, 5)))
json可以序列化的型別:元組,字典,int
json模組的四個方法:
- 用於網路傳輸:dumps、loads
- 用於檔案寫讀:dump、load
dumps、loads
import json
dic1 = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic) #序列化:將一個字典轉換成一個字串
print(type(str_dic),str_dic) #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json轉換完的字串型別的字典中的字串是由""表示的
dic2 = json.loads(str_dic) #反序列化:將一個字串格式的字典轉換成一個字典
#注意,要用json的loads功能處理的字串型別的字典中的字串必須由""表示
print(type(dic2),dic2) #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
list_dic = [1,['a','b','c'],2,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic)
print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 2, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]
dump、load
import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
with open('json_file','w')as f1:
json.dump(dic,f1) #dump方法接收一個檔案控制代碼,直接將字典轉換成json字串寫入檔案
with open('json_file')as f2:
dic2 = json.load(f2) #load方法接收一個檔案控制代碼,直接將檔案中的json字串轉換成資料結構返回
print(type(dic2),dic2)
五、pickle模組
pickle也是同於序列化和反序列化的模組,區別在於
- json,用於字串和 python資料型別間進行轉換
- pickle,用於python特有的型別 和 python的資料型別間進行轉換
pickle模組提供了四個功能:dumps、dump(序列化,存)、loads(反序列化,讀)、load (不僅可以序列化字典,列表...python中任意的資料型別都可序列化)
pickle比json強大,但是json是其他語言都支援的,pickle只有python支援。
import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic) # pickle轉化成一串二進位制內容,json是字串
dic2 = pickle.loads(str_dic)
print(dic2) #字典
和檔案相關的dump和load
import time
# 獲取時間物件
struct_time = time.localtime(100000000)
print(struct_time)
# pickle序列化
with open('pickle_file','wb')as f1:
pickle.dump(struct_time,f1)
# pickle反序列化
with open('pickle_file','rb')as f2:
struct_time2 = pickle.load(f2)
print(struct_time2.tm_year)
六、os模組
os.path中常用的檔案處理函式。
函式名 | 說明 |
---|---|
abspath(path) | 返回path所在的絕對路徑 |
dirname(path) | 返回目錄的路徑 |
exists(path) | 判斷檔案是否存在 |
getatime(filename) | 返回指定檔案的的最近訪問時間 |
getctime(path) | 返回指定檔案的建立時間 |
getmtime(path) | 返回指定檔案的最新的修改時間 |
getsize(filename) | 返回指定檔案的大小,單位是位元組 |
isdir(path) | 判斷是否為文目錄 |
isfile(path) | 判斷是否為檔案 |
split(path) | 分割檔名與路徑並返回一個列表 |
splitext(path) | 從路徑中分割檔案的拓展名 |
walk(top,func,arg) | 遍歷目錄數 |
getatime()、getctime()、getmtime()返回的都是時間戳。可通過time.gmtime([sec])轉換的得到一個物件,再通過該物件的tm_year,tm_mon,tm_mday等屬性獲取相應時間或日期
os模組下常用的檔案操作函式
os.remove(filename) # 刪除檔案
os.listdir() # 列出當前目錄的所有檔案,返回一個列表,如['an.txt','bn.txt','cn.txt']
os.rename('要修改的檔案、目錄名', '修改後的檔案、目錄名') # 檔案或目錄的重新命名
七、sys模組
# 直譯器相關操作
import sys
# sys.argv 傳遞給python指令碼的命令引數列表
# print(sys.argv[0]) # 指令碼名
# print('第一個引數', sys.argv[1])
# print('第二個引數', sys.argv[2])
# print(sys.platform) # 返回執行python指令碼的系統的平臺,當前是win32
# 直譯器尋找模組的路徑
# sys.path
八、time模組
time 和時間相關,主要用於顯示
時間戳:從時間元年(1970 1 1 00:00:00)到現在經過的秒數
struct_time型別,九個欄位組成,分別是tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst,
函式 | 說明 |
---|---|
time.time() | 返回一個float型別的時間戳 |
time.gmtime([seconds]) | 獲取格式化時間物件(struct_time型別) |
time.localtime([seconds]) | 獲取格式化的時間物件(struct_time型別) |
time.mktime(t) | 時間物件->時間戳 |
time.strftime(format[ ,t]) | 把時間按物件格式轉化成字串 |
time.strptime(str, format) | 把時間字串轉化為一個struct_time型別的 |
time.gmtime() | 獲取現在的時間戳,struct_time型別 |
time.asctime() | 返回當前時間的字串形式 |
import time
print(time.time()) # 獲取現在的時間戳
# print(time.gmtime(1)) # 元年經過1秒對應的時間物件
# 格式化的時間物件和字串之間的轉換
# s = time.strftime('year:%Y %m %d %H:%M:%S')
# print(s)
# 把時間字串轉換為時間物件
# time_obj = time.strptime('2020 10 1', '%Y %m %d')
# print(time_obj,type(time_obj))
九、datetime模組
datetime : 與日期時間相關,主要用於計算
三個主要類,只有他們能計算
date 需要年,月,日三個引數
datetime 需要年,月,日,時,分,秒六個引數
timedelta 需要一個時間段,可以是天,秒,微妙
# 時間變化量
# td = datetime.timedelta(days=1)
# print(td)
# 時間變化量會產生進位
# t = datetime.datetime(2020,10,10,10,1,59)
# d = datetime.timedelta(seconds=6)
# t = t + d
# print(t)
十、logging模組
python的logging模組提供了標準的日誌介面,你可以通過它儲存各種格式的日誌。
logging的日誌分為debug()、info()、warning()、error()、critical()五個級別
- debug() 除錯模式(詳細)
- info() 記錄(無錯誤)
- warning() 無錯誤但可能有潛在的危險
- error() 出現錯誤
- critical() 嚴重問題
1 基本用法
日誌列印
import logging
logging.warning('')
logging.critical('server is down')
# WARNING:root:user
# CRITICAL:root:server is down
日誌寫入檔案
import logging
logging.basicConfig(filename='log_test.log', level=logging.INFO)
logging.debug('debug')
logging.info('info')
logging.warning('warning')
# log_test.log只寫入warning和info資訊
在basicConfig中,filename指定了檔案路徑,level=logging.INFO是把日誌記錄設定為INFO,只輸入INFO或者比INFO級別更高的日誌(日誌級別過濾)。
自定義日誌格式
import logging
logging.basicConfig(filename='log_test.log', level=logging.DEBUG,format='%(asctime)s-%(name)s-%(filename)s-%(funcName)s-%(lineno)d-%(message)s'), # 引數格式固定
datefmt = '%m/%d/%/Y% %T:%M:%S'
logging.error('from sayhi...')
logging.debug('debug')
logging.info('info')
logging.warning('warning')
除了在日誌格式上加時間外,還可以自定義很多格式
引數格式介紹:
%(levelno)s # 列印數字形式的日誌級別(10對應debug,20對應info,30對應warning)
%(levelname)s # 列印文字形式的日誌級別 %(pathname)s # 呼叫日誌輸出函式的模組的完整路徑名
%(filename)s # 呼叫日誌輸出函式的模組的檔名
%(module)s # 呼叫日誌輸出函式的模組名
%(funcName)s # 呼叫日誌輸出函式的函式名
%(lineNo)d # 呼叫日誌輸出函式的語句所在的程式碼行(44)
%(created)f # 當前時間,用UNIX標準的表示是時間(一般時間用datafmt即可)
%(relaticeCreated)d # 輸出日誌資訊時,自Logger建立以來的毫秒數
%(asctime)s # 字串形式的當前時間,預設格式"2003-08-08 16:32:21,878",逗號後為毫秒數
%(thread)d # 執行緒ID
%(threadName)s # 執行緒名
%(process)d # 程序ID
%(message)s # 使用者輸出的訊息
日誌同時輸出到螢幕和檔案
Python使用logging模組記錄日誌涉及四個主要類:
1、logger提供了應用程式可以直接使用的介面;
2、handler將(logger建立的)日誌記錄傳送到合適的目的輸出;
3、filter對記錄的日誌過濾決定哪條日誌輸出;
4、formatter決定日誌記錄的最終輸出格式。
# 同時向檔案和螢幕上輸出 和 亂碼
fh = logging.FileHandler('tmp.log',encoding='utf-8')
# fh2 = logging.FileHandler('tmp2.log',encoding='utf-8')
sh = logging.StreamHandler()
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level= logging.DEBUG,
# handlers=[fh,sh,fh2]
handlers=[fh,sh]
)
logging.debug('debug 資訊錯誤 test2')
logging.info('warning 資訊錯誤 test2')
logging.warning('warning message test2')
logging.error('error message test2')
logging.critical('critical message test2')
日誌的切分
# 做日誌的切分
import time
from logging import handlers
sh = logging.StreamHandler()
rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5) # 按照大小做切割
fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8')
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level= logging.DEBUG,
# handlers=[fh,sh,fh2]
handlers=[fh,rh,sh]
)
for i in range(1,100000):
time.sleep(1)
logging.error('KeyboardInterrupt error %s'%str(i))
十一、functools模組
partial函式
functools存放了很多的工具函式,常用的兩個:
- partial函式(偏函式):綁定了一部分引數的函式。作用就是少傳引數,將部分引數和函式繫結,不需要傳入相同的引數。
- wraps函式:避免多個函式被兩個裝飾器裝飾時就報錯,因為兩個函式名一樣,第二個函式再去裝飾的話就報錯,最好是加上這個,程式碼更加健壯
# 案例一
def add(a,b):
return a+b
add = partial(add, 3)
add(6) # 9
# 案例二
def show(*args,**kwargs):
print(args)
print(kwargs)
show = partial(show, 1,2,3,4)
show() # (1,2,3,4) {}
show(name='an', age=11) # (1,2,3,4) {'name':'an', age:11}
wraps函式
wraps函式:新增裝飾器後函式名和函式的doc發生了改變,用此方法消除副作用。
def note(func):
def wrapper(*args):
print('note smomething')
return func(*args)
return wrapper
@note
def test():
'''函式文件'''
print('i am test')
test()
print(test.__doc__)
print(test.__name__)
# 列印結果
# note smomething
# i am test
# None
# wrapper
上述程式碼中發現test的__doc__屬性丟失,__name__屬性也變成了wrapper,使用wraps可以避免這個問題,
from functools import partial,wraps
def note(func):
@wraps(func) # 這裡加了wraps裝飾器
def wrapper(*args):
print('note smomething')
return func(*args)
return wrapper
@note
def test():
'''函式文件'''
print('i am test')
test()
print(test.__doc__)
print(test.__name__)
# 列印結果
# note smomething
# i am test
# 函式文件
# test
從上面可以看到test函式的doc和name屬性都沒有被改變。