一 猴子补丁
1.1 什么是猴子补丁?
1,这个词原来为Guerrilla Patch,杂牌军、游击队,说明这部分不是原装的,在英文里guerilla发音和gorllia(猩猩)相似,再后来就写了monkey(猴子)。
2,还有一种解释是说由于这种方式将原来的代码弄乱了(messing with it),在英文里叫monkeying about(顽皮的),所以叫做Monkey Patch。
名字听起来稀奇古怪的, 跟python的这个功能搭不上边, 所以我们直接来说功能吧!
1.2 猴子补丁的功能(一切皆对象)
1.拥有在模块运行时替换的功能, 例如: 一个函数对象赋值给另外一个函数对象(把函数原本的执行的功能给替换了)
1 2 3 4 5 6 7 8 9 10 11
|
class Monkey(): def play(self): print('猴子在玩')
class Dog(): def play(self): print('狗子在玩') m=Monkey() m.play() m.play=Dog().play m.play()
|
1.3 monkey patch的应用场景
这里有一个比较实用的例子,很多用到import json, 后来发现ujson性能更高,如果觉得把每个文件的import json改成import ujson as json成本较高, 或者说想测试一下ujson替换是否符合预期, 只需要在入口加上:
1 2 3 4 5 6 7 8 9 10
|
import json import ujson
def monkey_patch_json(): json.__name__ = 'ujson' json.dumps = ujson.dumps json.loads = ujson.loads monkey_patch_json() aa=json.dumps({'name':'lqz','age':19}) print(aa)
|
二 Gevent介绍
Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。
2.1 用法
2.2 示例1(遇到io自动切)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
import gevent def eat(name): print('%s eat 1' %name) gevent.sleep(2) print('%s eat 2' %name)
def play(name): print('%s play 1' %name) gevent.sleep(1) print('%s play 2' %name)
g1=gevent.spawn(eat,'lqz') g2=gevent.spawn(play,name='lqz') g1.join() g2.join()
|
2.3 示例二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
''' 上例gevent.sleep(2)模拟的是gevent可以识别的io阻塞,
而time.sleep(2)或其他的阻塞,gevent是不能直接识别的需要用下面一行代码,打补丁,就可以识别了
from gevent import monkey;monkey.patch_all()必须放到被打补丁者的前面,如time,socket模块之前
或者我们干脆记忆成:要用gevent,需要将from gevent import monkey;monkey.patch_all()放到文件的开头 ''' from gevent import monkey;monkey.patch_all()
import gevent import time def eat(): print('eat food 1') time.sleep(2) print('eat food 2')
def play(): print('play 1') time.sleep(1) print('play 2')
g1=gevent.spawn(eat) g2=gevent.spawn(play_phone) gevent.joinall([g1,g2]) print('主')
|
2.4 单线程的套接字服务端并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
import socket from threading import current_thread,Thread def socket_client(): cli=socket.socket() cli.connect(('127.0.0.1',8080)) while True: ss='%s say hello'%current_thread().getName() cli.send(ss.encode('utf-8')) data=cli.recv(1024) print(data)
for i in range(500): t=Thread(target=socket_client) t.start()
|
三 asyncio
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
import threading import asyncio
@asyncio.coroutine def hello(): print('Hello world! (%s)' % threading.currentThread()) yield from asyncio.sleep(1) print('Hello again! (%s)' % threading.currentThread())
loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
|