python并发库:concurrent.futures的使用

第一次接触futures这个库是在tornado中,4.0的tornado会经常的使用他,因为tornado本身的那个corouting的异步功能,是需要逻辑里面所调用的模块本身就支持异步才可以的。而且如果用futures之后,在一定程度上缓解了这个事情。

concurrent.futures 是python3新增加的一个库,用于并发处理,提供了多线程和多进程的并发功能
类似于其他语言里的线程池(也有一个进程池),他属于上层的封装,对于用户来说,不用在考虑那么多东西了。
Executor:两个子类ThreadPoolExecutor和ProcessPoolExecutor
Future:Executor.submit产生多任务

基本方法
class concurrent.futures.Executor (注:Executor为ThreadPoolExecutor或者ProcessPoolExecutor)
提供的方法如下:

submit(fn, *args, **kwargs)
fn:为需要异步执行的函数
args,kwargs:为给函数传递的参数

用submit注册你的函数,以及要传递的相关的参数,然后线程池里的线程会一块执行
下面是官方给的一个造成死锁的例子:


import time
def wait_on_b():
    time.sleep(5)
    print(b.result())  #b不会完成,他一直在等待a的return结果
    return 5

def wait_on_a():
    time.sleep(5)
    print(a.result())  #同理a也不会完成,他也是在等待b的结果
    return 6


executor = ThreadPoolExecutor(max_workers=2)
a = executor.submit(wait_on_b)
b = executor.submit(wait_on_a)

wait_on_a和wait_on_b函数会同时执行,因为使用了2个worker,所以会产生死锁

map(func, *iterables, timeout=None)
此map函数和python自带的map函数功能类似,只不过concurrent模块的map函数从迭代器获得参数后异步执行。并且,每一个异步操作,能用timeout参数来设置超时时间,timeout的值可以是int或float型,如果操作timeout的话,会raisesTimeoutError。如果timeout参数不指定的话,则不设置超时间。
func:为需要异步执行的函数
iterables:可以是一个能迭代的对象,例如列表等。每一次func执行,会从iterables中取参数。
timeout:设置每次异步操作的超时时间
例:

#!/bin/env python
#coding:utf-8
import time,re
import os,datetime
from concurrent import futures

data = [‘1‘,‘2‘]

def wait_on(argument):
   print argument
   time.sleep(2)
   return ‘ok‘

ex = futures.ThreadPoolExecutor(max_workers=2)
for i in ex.map(wait_on,data):
   print i

map函数异步执行完成之后,结果也是list,数据需要从list中取出
用法分别如下:

with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
    print(list(executor.map(sleeper, x)))
from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_go(nums, nprocs):
   nprocs=xxx
    with ProcessPoolExecutor(max_workers=nprocs) as executor:
        return {num:factors for num, factors in
                                zip(nums,
                                    executor.map(factorize_naive, nums))}

submit函数和map函数,根据需要,选一个使用即可。

下面附一个完整的concurrent例子:

#!/bin/env python
#coding:utf-8
import time,re,fcntl
import os,datetime
from concurrent import futures

count_list = list()
MinuteNum = 1
StartTime = datetime.datetime(2014, 4, 16, 19, 31, 0, 484870)
NowTime = datetime.datetime.now()
os.system(‘:>new.txt‘)

f_new = open(‘new.txt‘,‘a‘)

def test(CountTimeFormat):
   f = open(‘push_slave.stdout‘,‘r‘)
   for line in f.readlines():
       if re.search(CountTimeFormat,line):
           #获得文件专用锁
           fcntl.flock(f_new, fcntl.LOCK_EX)
           f_new.writelines(line)
           f_new.flush()
           #释放文件锁
           fcntl.flock(f_new, fcntl.LOCK_UN)
           break

while 1:
   AfterOneMinute = datetime.timedelta(minutes=MinuteNum)
   CountTime = AfterOneMinute+StartTime
   CountTimeFormat = CountTime.strftime(‘%Y-%m-%d %H:%M‘)
   MinuteNum = MinuteNum+1
   count_list.append(CountTimeFormat)
   if CountTimeFormat == "2014-04-23 16:00":
       break

def exec_cmd():
   with futures.ProcessPoolExecutor(max_workers=24) as executor:
       dict(( executor.submit(test, times), times) for times in count_list)

if __name__ == ‘__main__‘:
   exec_cmd()
   f_new.close()

下面再看看futures包的其他对象:

Future Objects
The Future class encapulates the asynchronous execution of a callable. Future instances are created by Executor.submit().

用cancel(),可以终止某个线程和进程的任务,返回状态为 True False
Future.cancel()
Attempt to cancel the call. If the call is currently being executed then it cannot be cancelled and the method will return False, otherwise the call will be cancelled and the method will return True.

判断是否真的结束了任务。
Future.cancelled()
Return True if the call was successfully cancelled.

判断是否还在运行
Future.running()
Return True if the call is currently being executed and cannot be cancelled.

判断是正常执行完毕的。 
Future.done()
Return True if the call was successfully cancelled or finished running.

针对result结果做超时的控制。 
Future.result(timeout=None)
Return the value returned by the call. If the call hasn’t yet completed then this method will wait up to timeout seconds. If the call hasn’t completed in timeout seconds then a TimeoutError will be raised. timeout can be an int or float.If timeout is not specified or None then there is no limit to the wait time.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值