目录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
# 待更新