模塊
模塊對我來說是什么
模塊對我來說,感覺就像親屬或者朋友已經走過的路,他們已經趟過的渾水、掉過的坑、踐行過的路線,全部提供給你,在你需要的時候請求幫助,借鑒他們的解決方法一樣。都是為了方便走好人生路,用最短的路程走到成功的終點。
內置模塊就像親屬,生來即有;自定義模塊就像自己走過一次的路,吃一塹長一智做好了攻略,下次按攻略來就可以;第三方模塊就像之后接觸到的朋友,他們成功的經驗借鑒給你,自己選擇,規避坑陷。
模塊調用的方法
import 模塊名
from 模塊名 import 方法名
emmm……python官方的開源模塊庫下載地址(防遺忘)
內置模塊
time/datetime模塊(還有一個calendar模塊,只了解過)
處理與時間有關的,感覺目前時間模塊我多用於測試(例如:time.sleep( ))和日志中。
特別重要,也是使用次數較多的:
在寫方法前先解釋下時間戳、結構化時間、字符串時間這些概念,當然也防止自己以后再看到時間戳的時候懷疑自己這是個啥玩意兒。
時間戳:1970紀元后經過的浮點秒數。
結構化時間:輸出結果是這種的,以時間是由什么結構組成的輸出,總之方便調用或修改。(tm_year,tm_mon,tm_mday,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)
字符串時間:就是正常顯示的時間
time.time():獲取當前時間的時間戳
這里例一個字符串時間t:
t='2019-01-01 10:00:00' f=time.strptime(t,'%Y-%m-%d %X') 這一步是將字符串時間t轉為結構化 f=time.mktime(f) 這一步是將結構化時間轉為時間戳 f=time.localtime(f) 這一步是將時間戳轉成結構化時間 f=time.strftime('%Y-%m-%d %X',f) 將結構化時間轉為字符串時間
字符串轉結構化用的是time.strptime()
結構化轉為字符串用的是time.strftime()
我以strp和strf來區別,p代表輸入,f代表格式化輸出,當然這是我的區別方法,至於是不是真的代表這個意思就不是很清楚了。
time是datetime的底層模塊,貌似我不怎么用到,這里就不詳寫了。
from datetime import datetime,timedelta # import datetime # print(datetime.now()) # # 時間對象 # f=datetime.now() # a=datetime.timestamp(datetime.now()) #將時間對象轉換成時間戳 # print(datetime.fromtimestamp(a)) #將時間戳轉成時間對象 print(datetime.now()-timedelta(days=2))
random、hmac模塊(隨機模塊,做驗證客戶端合法性的hmac模塊)
random模塊特別重要,實現隨機數功能,或隨機抽取這種的都需要用到它。
import random 內置的 print(random.random()) 0-1之間隨機小數 print(random.random(1,10)) 起始位置,終止位置 兩頭都包含 print(random.random(1,11,2)) 起始位置,終止位置(不包含),步長 print(random.choice([1,2,2])) 從可迭代、有序對象中隨機選 print(random.choices([1,2,3],k=2)) 選擇兩個,但有重復 print(random.sample([1,2,3],k=2)) 選擇兩個,沒有重復 li=[1,2,3,4,6] random.shuffle(li) 洗牌 打亂順序 print(li)
hmac模塊(做驗證客戶端合法性的,雖然我覺得它有可能不止用在驗證合法性。)
os.urandom(32):隨機的32位字節,每執行一次變一次
import os import hmac hmac=hmac.new(b’zhao’,os.urandom(32)) hmac.digest():以固定字節內容和隨機內容組合加密,然后與客戶端進行相同方法加密比較,如果相同則合法。
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/zhao') 給出當前平台使用的行終止符: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)
sys模塊
這個模塊我一般多用於反射和遞歸深度里
sys.argv 命令行參數List,第一個元素是程序本身路徑.之后的元素會傳入程序本身。第二個元素在sys.argv列表中索引為【1】 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 #獲取內存數據存到文件里的默認編碼
序列化模塊(json/pickle/shelve模塊)
序列化:差不多就是把任何數據類型轉換成str/bytes的過程。
import json/pickle/shelve
json模塊:
json.load() 將文件中的字符串轉換成字典
json.dump() 將字典轉換成字符串寫入到文件中
json.dumps() 將字典轉換成字符串
json.loads() 將字符串轉換成字典
pickle模塊:
pickle.load() 將文件中的字節轉換成字典
pickle.dump() 將字典轉換成字節寫入到文件中
pickle.dumps() 將字典轉換成字節
pickle.loads() 將字節轉換成字典
json和pickle的優缺點:
json:
優點:跨語言、體積小
缺點:只能支持Int\str\list\tuple\dict
pickle:
優點:專為python設計,支持python所有的數據類型
缺點:只能在python中使用,存儲數據占空間大
shelve模塊(不怎么了解,copy的):
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 f.close()
反序列化:
import shelve d = shelve.open('shelve_test') # 打開一個文件 print(d['names']) print(d['info_dic']) #del d['test'] #還可以刪除
hashlib模塊(加密)
hashlib包括:MD5,sha1,sha256,sha512
加密步驟:
- 先導入模塊
- 創建一個加密方式
- 將要加密的內容編碼成字節后加密
- 生成密文
import hashlib md5 = hashlib.md5(b‘alex’) md5.update(‘alex3714’.encode(‘utf-8’)) print(md5.hexdigest())
logging模塊(日志模塊)
日志模塊可以記錄正常的訪問操作日志,而且可以記錄錯誤、警告等信息,可以更直觀的告訴開發應該注意哪里的問題。
python的logging模塊提供了標准的日志接口,你可以通過它存儲各種格式的日志,logging的日志可以分為 debug(), info(), warning(), error() and critical()5個級別,下面我們看一下怎么用。
為什么要寫日志
一個卡務系統 : 記錄時間 地點 金額
誰在什么時候 刪掉了某一個用戶
某時某刻登錄了系統
檢測代碼是不是像我們想像的這樣執行的
寫文件 ,輸出到屏幕
f.write,print
時間格式,級別控制,更加便捷
*** logging模塊不能自動生成你需要的日志
logging模塊的使用
簡單配置法 *** 編碼問題
logger對象法 *****
import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S') logging.debug('debug message') # 調試 logging.info('info message') # 普通信息 logging.warning('warning message') # 警告 logging.error('error message') # 錯誤信息 logging.critical('critical message')# 嚴重錯誤
默認情況下 不打印warning以下級別的信息
1.中文顯示亂碼
2.不能同時輸出到文件和屏幕
logger對象的方式來使用logging模塊
首先 先創建logger對象
第二 創建一個文件操作符
第三 創建一個屏幕操作符
第四 創建一個格式
logger 綁定 文件操作符
logger 綁定 屏幕操作符
文件操作符 綁定格式
屏幕操作符 綁定格式
import logging
用logger
首先 先創建logger對象
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
第二 創建一個文件操作符
fh = logging.FileHandler('log',encoding='utf-8')
第三 創建一個屏幕操作符
sh = logging.StreamHandler()
第四 創建一個格式
fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger 綁定 文件操作符 logger.addHandler(fh) logger 綁定 屏幕操作符 logger.addHandler(sh) 文件操作符 綁定格式 fh.setFormatter(fmt) 屏幕操作符 綁定格式 sh.setFormatter(fmt) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message')
re模塊(正則)
正則表達式就是字符串的匹配規則,在多數編程語言里都有相應的支持,python里對應的模塊是re。
常用的表達式規則:
'.' :默認匹配除\n之外的任意一個字符
'^':匹配字符開頭
'$' :匹配字符結尾
'*' :匹配*號前的字符0次或多次
'+' :匹配前一個字符1次或多次
'?' :匹配前一個字符1次或0次
'{m}' :匹配前一個字符m次
'{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' :只從字符開頭匹配
'\Z' :匹配字符結尾,同$
'\d' :匹配數字0-9
'\D' :匹配非數字
'\w' :匹配[A-Za-z0-9]
'\W' :匹配非[A-Za-z0-9]
's' :匹配空白字符
'(?P<name>...)' :分組匹配
re的匹配語法:
找到所有的符合正則表達式的內容
ret=re.findall('正則表達式','內容') print(ret)
找到第一個符合正則表達式的內容就停止,通過group取值,找不到時ret返回None,ret.group報錯,所以一般if ret:和ret.group搭配使用。
ret=re.search('正則表達式','內容') if ret: print(ret.group())
從頭開始找第一個。用ret.group取值
ret=re.match('正則表達式','內容') print(ret.group())
找到符合條件的默認替換所有,設置換n次
ret=re.sub(‘正則表達式’,’新值’,’完整字符串’)
ret=re.sub(‘正則表達式’,’新值’,’完整字符串’,’n’)
找到符合條件的替換,並返回出現了幾次
ret=re.subn(‘正則表達式’,’新值’,’完整字符串’) print(ret)
分為列表
ret=re.split(‘\d+’,’內容’)
abc模塊(抽象類)
抽象類概念:是一個特殊的類,只能被繼承,不能實例化
抽象類的意義:抽象類中只能有抽象方法(沒有實現功能),該類不能被實例化,只能被繼承,且子類必須實現抽象方法。這一點與接口有點類似,但其實是不同的,看以下示例。
示例代碼:
#一切皆文件 import abc #利用abc模塊實現抽象類 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定義抽象方法,無需實現功能 def read(self): '子類必須定義讀功能' pass @abc.abstractmethod #定義抽象方法,無需實現功能 def write(self): '子類必須定義寫功能' pass # class Txt(All_file): # pass # # t1=Txt() #報錯,子類沒有定義抽象方法 class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('文本數據的讀取方法') def write(self): print('文本數據的讀取方法') class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('硬盤數據的讀取方法') def write(self): print('硬盤數據的讀取方法') class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法 def read(self): print('進程數據的讀取方法') def write(self): print('進程數據的讀取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #這樣大家都是被歸一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)
multiprocessing模塊(多進程模塊)
第一次接觸到它是在多進程中,使用它里面的Process類可以達到異步傳輸的效果,使用方法如下:
import time from multiprocessing import Process def func(a,b,c): time.sleep(1) print(a,b,c) if __name__ == '__main__': Process(target=func,args=(1,2,3)).start() #這里的target是目標的意思,固定搭配 Process(target=func,args=(2,3,4)).start() #所有的Process()都是子進程,子進程都放在if下。 Process(target=func,args=(3,4,5)).start()
開啟的子進程:
需要注意的是:下面標紅區域必須是元組,當只傳一個值時,必須也為元組形式。
import time from multiprocessing import Process def func(a): time.sleep(1) print(a) if __name__ == '__main__': Process(target=func,args=(1,)).start() Process(target=func,args=(2,)).start()
multiprocessing中的方法:
Lock 鎖
同一時間點上只有一個進程可以進行操作,lock.acquire() 獲取鑰匙 如果這個人沒拿走鑰匙,那么就可以直接進入下面的代碼;如果有人拿走了鑰匙,則需等待鑰匙歸還后才可以進入下面的代碼。lock.release() 歸還鑰匙
鎖的應用場景:當多個進程需要操作同一個文件/數據庫時,需要通過加鎖
Queue 隊列
隊列是進程安全的,自帶了鎖調節生產者的個數或者消費者的個數來讓程序的效率達到最平衡和最大化
Manager 共享資源
Manager類的作用共享資源,manger的的優點是可以在poor進程池中使用,缺點是windows下環境下性能比較差,因為windows平台需要把Manager.list放在if name='main'下,而在實例化子進程時,必須把Manager對象傳遞給子進程,否則lists無法被共享,而這個過程會消耗巨大資源,因此性能很差。
threading模塊(處理多線程)
threading模塊和multiprocessing模塊
先有的threading模塊
沒有池的功能
multiprocessing完全模仿threading模塊完成的
實現了池的功能
concurrent.futures
實現了線程池\進程池
一個進程中的多線程:
import os import time from threading import Thread def func(i): time.sleep(1) print('in func', i,os.getpid()) print('in main', os.getpid()) for i in range(20): Thread(target=func,args=(i,)).start()
注:
在線程部分不需要通過import來為新的線程獲取代碼
因為新的線程和之前的主線程共享同一段代碼
不需要import 也就不存在在子線程中又重復了一次創建線程的操作
所以就不必要if __name__==’__main__’
threading 與 multiprocessing效率對比(代碼):
import time from multiprocessing import Process from threading import Thread def func(a): a += 1 if __name__ == '__main__': start = time.time() t_l = [] for i in range(100): t = Thread(target=func, args=(i,)) #多線程 t.start() t_l.append(t) for t in t_l: t.join() print('Thread :', time.time() - start) start = time.time() t_l = [] for i in range(100): t = Process(target=func, args=(i,)) #多進程 t.start() t_l.append(t) for t in t_l: t.join() print('Process', time.time() - start)
結果:
多個線程之間的全局變量是共享的,進程是數據隔離的(代碼):
from threading import Thread tn = 0 def func(): global tn tn += 1 t_l = [] for i in range(100): t = Thread(target=func) t.start() t_l.append(t) for t in t_l: t.join() print(tn)
結果:
進程是數據隔離的(代碼):
from multiprocessing import Process pn = 0 def func(): global pn pn += 1 if __name__ == '__main__': p_l = [] for i in range(100): p = Process(target=func) p.start() p_l.append(p) for p in p_l: p.join() print(pn)
結果:
threading模塊提供的方法:
threading.currentThread(): 返回當前的線程變量。
threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啟動后、結束前,不包括啟動前和終止后的線程。
threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
import os from threading import Thread, currentThread def func(): t = currentThread() print(t.name, t.ident, os.getpid()) tobj = Thread(target=func) tobj.start() print('tobj :', tobj) t2 = currentThread() print(t2.name, t2.ident, os.getpid())
線程有terminate么?
沒有terminate 不能強制結束
所有的子線程都會在執行完所有的任務之后自動結束