上下文管理器的任務是:代碼塊執行前準備,代碼塊執行後收拾html
如何打開一個文件,並寫入"hello world"python
filename="my.txt"
mode="w"
f=open(filename,mode)
f.write("hello world")
f.close()
當發生異常時(如磁盤寫滿),就沒有機會執行第5行。固然,咱們能夠採用try-finally語句塊進行包裝:安全
writer=open(filename,mode)
try:
writer.write("hello world")
finally:
writer.close()
當咱們進行復雜的操做時,try-finally語句就會變得醜陋,採用with語句重寫:多線程
with open(filename,mode) as writer:
writer.write("hello world")
as指代了從open()函數返回的內容,並把它賦給了新值。with完成了try-finally的任務。框架
with語句的做用相似於try-finally,提供一種上下文機制。要應用with語句的類,其內部必須提供兩個內置函數__enter__和__exit__。前者在主體代碼執行前執行,後者在主體代碼執行後執行。as後面的變量,是在__enter__函數中返回的。ide
class echo():
def output(self):
print "hello world"
def __enter__(self):
print "enter"
return self #能夠返回任何但願返回的東西
def __exit__(self,exception_type,value,trackback):
print "exit"
if exception_type==ValueError:
return True
else:
return Flase
>>>with echo as e:
e.output()
輸出:
enter
hello world
exit
contextlib模塊的做用是提供更易用的上下文管理器,它是經過Generator實現的。contextlib中的contextmanager做爲裝飾器來提供一種針對函數級別的上下文管理機制,經常使用框架以下:函數
from contextlib import contextmanager
@contextmanager
def make_context():
print 'enter'
try:
yield "ok"
except RuntimeError,err:
print 'error',err
finally:
print 'exit'
>>>with make_context() as value:
print value
輸出爲:
enter
ok
exit
其中,yield寫入try-finally中是爲了保證異常安全(能處理異常)as後的變量的值是由yield返回。yield前面的語句可看做代碼塊執行前操做,yield以後的操做能夠看做在__exit__函數中的操做。性能
以線程鎖爲例:ui
@contextlib.contextmanager
def loudLock():
print 'Locking'
lock.acquire()
yield
print 'Releasing'
lock.release()
with loudLock():
print 'Lock is locked: %s' % lock.locked()
print 'Doing something that needs locking'
#Output:
#Locking
#Lock is locked: True
#Doing something that needs locking
#Releasing
with open(filename,mode) as reader,open(filename1,mode1) as writer:
writer.write(reader.read())
file類直接支持上下文管理器API,但有些表示打開句柄的對象並不支持,如urllib.urlopen()返回的對象。還有些遺留類,使用close()方法而不支持上下文管理器API。爲了確保關閉句柄,須要使用closing()爲它建立一個上下文管理器(調用類的close方法)。url
協程,又稱微線程,纖程。英文名Coroutine。
優勢1: 協程極高的執行效率。由於子程序切換不是線程切換,而是由程序自身控制,所以,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優點就越明顯。
優勢2: 不須要多線程的鎖機制,由於只有一個線程,也不存在同時寫變量衝突,在協程中控制共享資源不加鎖,只須要判斷狀態就行了,因此執行效率比多線程高不少。
由於協程是一個線程執行,那怎麼利用多核CPU呢?最簡單的方法是多進程+協程,既充分利用多核,又充分發揮協程的高效率,可得到極高的性能。
import time
import queue
def consumer(name):
print("--->ready to eat baozi...")
while True:
new_baozi = yield
print("[%s] is eating baozi %s" % (name,new_baozi))
#time.sleep(1)
def producer():
r = con.__next__()
r = con2.__next__()
n = 0
while 1:
time.sleep(1)
print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) )
con.send(n)
con2.send(n+1)
n +=2
if __name__ == '__main__':
con = consumer("c1")
con2 = consumer("c2")
p = producer()
greenlet是一個用C實現的協程模塊,相比與python自帶的yield,它可使你在任意函數之間隨意切換,而不需把這個函數先聲明爲generator
from greenlet import greenlet
def test1():
print(12)
gr2.switch()
print(34)
gr2.switch()
def test2():
print(56)
gr1.switch()
print(78)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
import gevent
import requests,time
start=time.time()
def f(url):
print('GET: %s' % url)
resp =requests.get(url)
data = resp.text
print('%d bytes received from %s.' % (len(data), url))
gevent.joinall([
gevent.spawn(f, 'https://www.python.org/'),
gevent.spawn(f, 'https://www.yahoo.com/'),
gevent.spawn(f, 'https://www.baidu.com/'),
gevent.spawn(f, 'https://www.sina.com.cn/'),
])
# f('https://www.python.org/')
#
# f('https://www.yahoo.com/')
#
# f('https://baidu.com/')
#
# f('https://www.sina.com.cn/')
print("cost time:",time.time()-start)
參考:http://www.cnblogs.com/yuanchenqi/articles/6248025.html