目錄php
一. 經常使用模塊 - hashlibhtml
二. 經常使用模塊 - hmacjava
三. 經常使用模塊 - loggingpython
四. 經常使用模塊 - renginx
五. 經常使用模塊 - requestsgit
六. 經常使用模塊 - paramikoweb
一. 經常使用模塊 - hashlib正則表達式
hash: 一種算法, 3.x裏代替了md5模塊和sha模塊, 主要提供 SHA1, SHA224, SHA256, SHA384, SHA512, MD5 算法算法
特色:數據庫
1 import hashlib 2 3 m=hashlib.md5()# m=hashlib.sha256() 4 m.update('hello'.encode('utf8')) 5 print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 6 m.update('alvin'.encode('utf8')) 7 print(m.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af 8 9 m2=hashlib.md5() 10 m2.update('helloalvin'.encode('utf8')) 11 print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af 12 13 ''' 14 注意: 把一段很長的數據update屢次, 與一次update這段長數據, 獲得的結果同樣 15 可是update屢次爲校驗大文件提供了可能. 16 '''
以上加密算法雖然依然很是厲害, 但時候存在缺陷, 即: 經過撞庫能夠反解. 因此, 有必要對加密算法中添加自定義key再來作加密.
1 import hashlib 2 # ######## 256 ######## 3 hash = hashlib.sha256('898oaFs09f'.encode('utf8')) 4 hash.update('alvin'.encode('utf8')) 5 print (hash.hexdigest()) 6 #e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
二. 經常使用模塊 - hmac
HMAC的應用
hmac主要應用在身份驗證中,它的使用方法是這樣的:
在這個過程當中,可能遭到安全攻擊的是服務器發送的隨機值和用戶發送的hmac結果,而對於截獲了這兩個值的黑客而言這兩個值是沒有意義的,絕無獲取用戶密碼的可能性,隨機值的引入使hmac只在當前會話中有效,大大加強了安全性和實用性。大多數的語言都實現了hmac算法,好比php的mhash、python的hmac.py、java的MessageDigest類,在web驗證中使用hmac也是可行的,用js進行md5運算的速度也是比較快的。
1 import hmac 2 h = hmac.new('alvin'.encode('utf8')) 3 h.update('hello'.encode('utf8')) 4 print (h.hexdigest()) 5 #320df9832eab4c038b6c1d7ed73a5940
三. 經常使用模塊 - logging
不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲 debug()
, info()
, warning()
, error()
and critical() 5個級別,
下面咱們看一下怎麼用。
1 import logging 2 3 logging.warning("user [alex] attempted wrong password more than 3 times") 4 logging.critical("server is down") 5 6 #輸出 7 WARNING:root:user [alex] attempted wrong password more than 3 times 8 CRITICAL:root:server is down
上面是最簡單的應用. 但明顯還不足以與nginx, apache等成熟軟件的日誌媲美. 若是想達到nginx這種日誌的效果咱們須要深刻了解一下這個模塊.
logging : https://docs.python.org/3.6/library/logging.html
這個包中包含了如下幾個類:
因爲我的能力問題, 目前只說明Logger Handler Formatter 三個類的關係與用法. 其他三種等往後在更新.
Logger Handler Formatter
他們的關係請看下圖.
Formatter 能夠綁定給 Handler, Handler 能夠綁定給Logger
如圖上所示, Logger1 擁有 Handler1與Handler2的處理配置, 還擁有 Formatter 的格式配置. Logger2 擁有 Handler2與Handler3 的處理配置, 還擁有 Formatter 的格式配置.
那咱們如今來看一下每一個類到底都有什麼功能.
Logger
1 Logger.propagate 2 若爲True, 日誌信息除了傳遞給該logger的handler以外, 也被傳遞給上游logger的handler, 不會考慮上游logger的級別與filter限制 3 若爲False, 日誌信息不會傳遞給上游logger的handler 4 構造函數設置該屬性爲True 5 6 Logger.setLevel(lvl) 7 設置該logger級別爲lvl. 低於lvl的日誌信息將被忽略. 8 當建立一個根logger時, 默認級別爲WARNING 9 當建立一個非根logger時, 默認級別爲NOTSET 10 11 Logger.isEnabledFor(lvl) 12 代表lvl級別的信息是否會被該logger處理. 該方法首先檢查由logging.disable(lvl)設置的模塊級的級別, 而後檢查由getEffective()決定的該logger的有效級別. 13 判斷這個級別的信息是否會被處理. 14 15 Logger.getEffectiveLevel() 16 獲取該logger處理信息的級別 17 18 Logger.getChild(suffix) 19 20 Logger.debug(msg, *args, **kwargs) 21 給該logger記錄一條級別爲 DEBUG 的信息, msg爲消息格式字符串,args爲經過字符串格式操做符合併到msg的參數。(注意這意味着能夠在格式字符串中使用關鍵字和一個字典參數。) 22 23 kwargs中有兩個關鍵字參數會被檢查:第一個是exc_info,若是它不爲false,異常信息會被添加到日誌消息。若是有提供異常元組(格式爲sys.exc_info()返回值的格式),使用該元組;不然調用sys.exc_info()來獲得異常信息。 24 第二個檢查的關鍵字參數是extra,能夠給它傳遞一個字典,用來填充LogRecord的__dict__,LogRecord用以表示日誌事件,且有自定義屬性。你能夠隨意使用這些自定義屬性。例如,它們能夠合併到日誌消息中。示例: 25 26 FORMAT = '%(asctime)-15s %(clientip)s %(user)-8s %(message)s' 27 logging.basicConfig(format=FORMAT) 28 d = {'clientip': '192.168.0.1', 'user': 'fbloggs'} 29 logger = logging.getLogger('tcpserver') 30 logger.warning('Protocol problem: %s', 'connection reset', extra=d) 31 將會打印 32 2006-02-08 22:20:02,165 192.168.0.1 fbloggs Protocol problem: connection reset 33 34 extra的字典的鍵不該該與日誌系統使用的鍵衝突。(參見Formatter文檔瞭解日誌系統所用鍵的信息。) 35 若是決定要在日誌消息中使用這些屬性,使用時要當心。拿上面的例子,Formatter的格式字符串期待LogRecord的屬性字典中有'clientip'和'user'。若是缺失的話,該消息就不會被記錄,由於會發生字符串格式異常。在這種狀況下,你老是要傳遞帶這些鍵的extra字典。 36 這可能有些麻煩,它主要在一些特定的環境下使用。若有一個多線程服務器,相同的代碼會在許多上下文執行,而感興趣的條件在上下文才會出現(如上例中的遠端客戶端IP地址和已認證用戶名)。在這種環境下,極可能對特殊的Handler使用特定的Formatter。 37 38 Logger.info(msg, *args, **kwargs) 39 給該logger記錄一條級別爲 INFO 的信息 40 41 Logger.warning(msg, *args, **kwargs) 42 給該logger記錄一條級別爲 WARNING 的信息 43 44 Logger.error(msg, *args, **kwargs) 45 給該logger記錄一條級別爲 ERROR 的信息 46 47 Logger.critical(msg, *args, **kwargs) 48 給該logger記錄一條級別爲 CRITICAL 的信息 49 50 Logger.log(lvl, msg, *args, **kwargs) 51 給該logger記錄一條級別爲 lvl 的信息。 52 53 Logger.exception(msg, *args, **kwargs) 54 給該logger記錄一條級別爲 ERROR 的信息。異常信息將添加到日誌信息中。該方法應該只在異常處理器調用。 55 56 Logger.addFilter(filt) 57 添加指定的filter filt 到該logger。 58 59 Logger.removeFilter(filt) 60 刪除該logger中的filter filt。 61 62 Logger.filter(record) 63 對record應用該logger的filters,若是該record應該被處理,返回真。輪流調用filters,直到有一個返回假。若是沒有filter返回假值,該record將會被處理(傳遞給handlers)。若是有一個返回了假值,將不會對record作進一步的處理。 64 65 Logger.addHandler(hdlr) 66 將指定的handlerhdlr添加到logger中。 67 68 Logger.removeHandler(hdlr) 69 從logger中移除指定的handler hdlr。 70 71 Logger.findCaller(stack_info=False) 72 查找調用者的源碼文件名和行號。以3元組的形式返回文件名,行號和函數名。 73 2.4版本中的變更: 函數名被加入進來。在早期版本中,以2元組形式返回文件名和行號。 74 75 Logger.handle(record) 76 處理一個record,將它傳給該logger及其祖先的全部的handler(直到propagate爲假爲止)。該方法用於從套接字接收到的反序列化的record,以及那些本地建立的。使用filter()日誌級別過濾會應用。 77 78 Logger.makeRecord(name, lvl, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None) 79 這是一個工廠方法,能夠在子類中覆蓋它來建立特定的LogRecord實例。 80 版本2.5中的改變:添加func 和extra 參數。 81 82 Logger.hasHandlers() 83 檢查是否此日誌記錄器已配置的任何處理程序。這是經過尋找此日誌記錄器中的處理程序和其父母記錄器層次結構中。若是處理程序被發現,不然錯誤將返回 True。方法中止搜索層次結構中向上,每當與 '傳播' 屬性設置爲 false 的記錄器發現 — — 這將是最後一個記錄器,檢查存在的處理程序。 84 3.2 版中的新增功能。
Handlers
Handlers是個基類, 在他下面有不少子類來實現了各類handlers的配置方向
StreamHandler | 流Handler |
FileHandler | 文件Handler |
NullHandler | 空Handler |
WatchedFileHandler | 守衛文件Handler |
BaseRotatingHandler | 基本輪詢Handler |
RotatingFileHandler | 輪詢文件Handler |
TimedRotatingFileHandler | 時間輪詢文件Handler |
SocketHandler | Socket Handler |
DatagramHandler | 數據報Handler |
SysLogHandler | 系統日誌Handler |
NTEventLogHandler | Windows事件日誌Handler |
SMTPHandler | SMTP協議Handler |
MemoryHandler | 內存Handler |
HTTPHandler | HTTP協議Handler |
QueueHandler | 隊列Handler |
QueueListener | 隊列監聽器 |
# 每一個Handler具體使用方法, 請參考: http://python.usyiyi.cn/translate/python_278/library/logging.handlers.html#module-logging.handlers
# logging模塊中文文檔: http://python.usyiyi.cn/python_278/library/logging.html
# 待整理文檔內容到博客中.
按天分割日誌, 並保留最近七天的配置:
1 # /usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @Author: kys1230 4 # @Email: kys1230@126.com 5 # @Date: 2017-02-22 14:36:25 6 7 8 import logging 9 import logging.handlers 10 11 filename = "access.log" 12 13 # 建立logger對象, 設置logger的日誌級別 14 acc_log = logging.getLogger("access") 15 acc_log.setLevel(logging.INFO) 16 17 # 建立文件Handler 18 fh = logging.handlers.TimedRotatingFileHandler(filename, when='D', interval=1, backupCount=7) 19 20 # 建立格式 21 fmt = logging.Formatter("%(asctime)s - %(name)s %(filename)s:%(funcName)s:%(lineno)d %(levelname)s %(message)s") 22 23 # 將格式綁定到Handler 24 fh.setFormatter(fmt) 25 26 # 將Handler綁定到Logger 27 acc_log.addHandler(fh) 28 29 # 使用Logger 30 acc_log.debug("debug") 31 acc_log.info("info") 32 acc_log.warning("warning") 33 acc_log.error("error") 34 acc_log.critical("critical")
四. 經常使用模塊 - re
下圖列出了Python支持的正則表達式元字符和語法:
數量詞的貪婪模式與非貪婪模式
正則表達式一般用於在文本中查找匹配的字符串. Python裏數量詞默認是貪婪的(在少數語言裏也多是默認非貪婪), 老是嘗試匹配儘量多的字符;非貪婪的則相反, 老是嘗試匹配儘量少的字符. 例如: 正則表達式"ab*"若是用於查找"abbbc", 將找到"abbb". 而若是使用非貪婪的數量詞"ab*?", 將找到"a".
反斜槓的困擾
與大多數編程語言相同, 正則表達式裏使用"\"做爲轉義字符, 這就可能形成反斜槓困擾. 假如你須要匹配文本中的字符"\", 那麼使用編程語言表示的正則表達式裏將須要4個反斜槓"\\\\": 前兩個和後兩個分別用於在編程語言裏轉義成反斜槓, 轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓. Python裏的原生字符串很好地解決了這個問題, 這個例子中的正則表達式可使用r"\\"表示. 一樣, 匹配一個數字的"\\d"能夠寫成r"\d". 有了原生字符串, 你不再用擔憂是否是漏寫了反斜槓, 寫出來的表達式也更直觀.
匹配模式
正則表達式提供了一些可用的匹配模式, 好比忽略大小寫、多行匹配等, 這部份內容將在Pattern類的工廠方法re.compile(pattern[, flags])中一塊兒介紹.
re模塊方法
re.compile(pattern, flags=0) # 將字符串形式的正則表達式編譯爲 Pattern對象
1 prog = re.compile(pattern) 2 result = prog.match(string) 3 # 上面用法等價於下面的用法, 區別在於能夠將正則表達式的規則保存到對象中, 以便以後重複使用. 4 result = re.match(pattern, string)
Flags:
1 a = re.compile(r"""\d + # the integral part 2 \. # the decimal point 3 \d * # some fractional digits""", re.X) 4 b = re.compile(r"\d+\.\d*")
re.search(pattern, string, flags=0) # 從頭開始將內容與pattern進行匹配, 若是匹配則返回一個 匹配對象, 若是匹配不到, 最終返回None
re.match(pattern, string, flags=0) # match 至關於 search的正則表達式前加了個^, 他僅從數據的開始位置開始匹配.
re.fullmatch(pattern, string, flags=0) # 將string與pattern進行匹配, 若是徹底匹配則返回 匹配對象, 不然 返回None, 這個方法是3.4中新增長的.
1 pattern = "o[gh]" 2 print(re.fullmatch(pattern, "dog")) # 返回None,沒有og|oh開頭 3 print(re.fullmatch(pattern, "ohr")) # 返回None,不是整串徹底匹配,雖然有Oh開頭,可是還包含字母r 4 print(re.fullmatch(pattern, "og")) # 返回og,徹底匹配
re.split(pattern, string, maxsplit=0, flags=0) # str.split只能按照某個分隔符分割, re.split 能夠按照正則規則分割. 在3.1版本後 添加了flags參數
re.findall(pattern, string, flags=0) # 獲取所有的匹配字符,返回一個全部匹配字符串的列表
re.finditer(pattern, string, flags=0) # findall相似,只是 finditer 返回的是一個迭代器
1 import re 2 data = "My name is Kys1230" 3 for i in re.finditer("\w+", data): 4 print(i.group()) 5 # 執行結果 6 My 7 name 8 is 9 Kys1230
re.sub(pattern, repl, string, count=0, flags=0) # 將正則表達式匹配的字符串替換爲新字符串
1 >>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):', 2 ... r'static PyObject*\npy_\1(void)\n{', 3 ... 'def myfunc():') 4 'static PyObject*\npy_myfunc(void)\n{'
若是repl是個函數, 會將正則匹配到的字符串逐一傳遞給函數執行, 將函數的返回值加入到結果中. 例如:
1 >>> def dashrepl(matchobj): 2 ... if matchobj.group(0) == '-': return ' ' 3 ... else: return '-' 4 >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files') 5 'pro--gram files'
re.subn(pattern, repl, string, count=0, flags=0) # 與re.sub相似, 返回的是元組(新字符串, 替換的次數)
re.escape(string) # 用於將string中的正則表達式元字符如 * + ? 等以前加上轉義符再返回, 在須要大量匹配元字符時有那麼一點用. 3.3版本後 "_" 再也不進行轉移
re.purge() # 清空緩存中的正則表達式
正則表達式對象的 方法 與 屬性:
regex.search(string[, pos[, endpos]]) # 從字符串string的開始位置pos開始匹配正則表達式, 到位置endpos結束匹配. 匹配成功返回 match對象, 不然返回None
1 >>> pattern = re.compile("d") 2 >>> pattern.search("dog") # Match at index 0 3 <_sre.SRE_Match object; span=(0, 1), match='d'> 4 >>> pattern.search("dog", 1) # No match; search doesn't include the "d"
regex.match(string[, pos[, endpos]]) # 指定從字符串string頭部或者指定位置的頭部匹配
1 >>> pattern = re.compile("o") 2 >>> pattern.match("dog") # No match as "o" is not at the start of "dog". 3 >>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog". 4 <_sre.SRE_Match object; span=(1, 2), match='o'>
regex.fullmatch(string[, pos[, endpos]]) # 當整個string與正則表達式匹配時返回match對象, 不然返回None, 3.4版本中新增方法
1 >>> pattern = re.compile("o[gh]") 2 >>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog". 3 >>> pattern.fullmatch("ogre") # No match as not the full string matches. 4 >>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits. 5 <_sre.SRE_Match object; span=(1, 3), match='og'>
regex.split(string, maxsplit=0) # 本方法與re.split()同樣
regex.findall(string[, pos[, endpos]]) # 與re.findall()同樣, 本方法接收參數pos與endpos參數, 能夠指定開始位置和結束位置
regex.finditer(string[, pos[, endpos]]) # 與re.finditer()同樣, 本方法接收參數pos與endpos參數, 能夠指定開始位置和結束位置
regex.sub(repl, string, count=0) # 與re.sub()同樣
regex.subn(repl, string, count=0) # 與re.subn()同樣
regex.flags # 待更新
The regex matching flags. This is a combination of the flags given to compile(), any (?...) inline flags in the pattern, and implicit flags such as UNICODE if the pattern is a Unicode string.
regex.groups # 正則表達式匹配分組的數量
pattern = re.compile('(?P<style>[^|]*)\|(?P<tags>[^|]*)') print(pattern.findall('OL|AAAAA')) print(pattern.groups) # 結果輸出以下: [('OL', 'AAAAA')] 2
regex.groupindex # 返回分組的名稱和序號, 以字典方式返回. 若是沒有返回空字典
pattern = re.compile('(?P<style>[^|]*)\|(?P<tags>[^|]*)') print(pattern.findall('OL|AAAAA')) print(pattern.groupindex) # 結果輸出以下: [('OL', 'AAAAA')] {'style': 1, 'tags': 2}
regex.pattern # 已經編譯的正則表達式的字符串
pattern = re.compile('(?P<style>[^|]*)\|(?P<tags>[^|]*)') print(pattern.findall('OL|AAAAA')) print(pattern.pattern) # 結果輸出以下: regex.pattern [('OL', 'AAAAA')] (?P<style>[^|]*)\|(?P<tags>[^|]*)
Match(匹配)對象
match對象 是經過正則表達式匹配成功以後返回的對象, 若是不成功也會返回, 不過其布爾值爲False. 所以, 判斷是否匹配成功, 只要判斷match對象的布爾值就能夠, 簡單的就是使用if語句來判斷.
match = re.search(pattern, string) if match: process(match)
match對象支持下面的方法和屬性:
match.expand(template) # 在模板字符串template中指定位置替換爲指定分組的內容, 可能過索引(\1,\2)或組名稱(\g<1>, \g<name>)來引用.
pattern = re.compile('(?P<style>[^|]*)\|(?P<tags>[^|]*)') match = pattern.match('OL|AAAAA') print(pattern.groups) print(pattern.groupindex) print(match.expand(r'這是一個測試\2, 沒錯')) # 輸出結果以下: 2 {'style': 1, 'tags': 2} 這是一個測試AAAAA, 沒錯
match.group([group1, ...]) # 返回分組中子分組的結果. 若是隻有一個參數, 看成一個字符串返回. 若是有多個參數, 使用元組返回. 若是沒有參數輸入, 默認返回第一組的結果. 組號的範圍在[1, 99]之間. 若是輸入組號爲負數, 或者大於匹配的分組最大值, 就拋出IndexError異常.
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist") >>> m.group(0) # The entire match 'Isaac Newton' >>> m.group(1) # The first parenthesized subgroup. 'Isaac' >>> m.group(2) # The second parenthesized subgroup. 'Newton' >>> m.group(1, 2) # Multiple arguments give us a tuple. ('Isaac', 'Newton') >>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") >>> m.group('first_name') 'Malcolm' >>> m.group('last_name') 'Reynolds' >>> m.group(1) 'Malcolm' >>> m.group(2) 'Reynolds' >>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times. >>> m.group(1) # Returns only the last match. 'c3'
match.groups(default=None) # 使用元組返回全部匹配的分組, 若是有分組沒有匹配, 就返回None. 若是有設置參數, 就會使用參數來替換相應沒有匹配到的分組.
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632") >>> m.groups() ('24', '1632') >>> m = re.match(r"(\d+)\.?(\d+)?", "24") >>> m.groups() # Second group defaults to None. ('24', None) >>> m.groups('0') # Now, the second group defaults to '0'. ('24', '0')
match.groupdict(default=None) # 以字典的方式返回分組命名的匹配結果. 若是沒有匹配成的分組, 以參數替換, 若是沒有參數, 就默認爲None替換.
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds") >>> m.groupdict() {'first_name': 'Malcolm', 'last_name': 'Reynolds'}
match.start([group])
match.end([group]) # 返回匹配組的開始位置和結束位置. 參數是group組號, 默認爲0, 就全部組都返回.
>>> email = "tony@tiremove_thisger.net" >>> m = re.search("remove_this", email) >>> email[:m.start()] + email[m.end():] 'tony@tiger.net'
match.span([group]) # 返回匹配對象組的開始位置和結束位置(m.start(group), m.end(group)), 格式是元組方式. 若是沒有匹配任何組返回(-1, -1).
match.pos
match.endpos # 在search和match裏使用開始位置和結束位置.
match.lastindex # 保存最後分組的值. 若是沒有組, 返回None.
match.lastgroup # 待更新
The name of the last matched capturing group, or None if the group didn’t have a name, or if no group was matched at all.
match.re # 在search和match中使用的正則表達式對象.
match.string # 傳給search或match進行匹配的字符串.
五. 經常使用模塊 - requests
# 待更新
六. 經常使用模塊 - paramiko
# 待更新