RF可用的多线程装饰器

RF本身没有多线程的库,我们可以使用类似下面的方法,并对外公开parseArgmultipleArg两个方法(写到测试类里面),给需要并发的函数套上装饰器,即可实现多线程执行函数。由于可以只传单个的参数,因此并不影响函数的单线程运行。
比如在RIDE/RED内可以写成这样的调用
多线程关键字是baidusearch

${arg1}parseArgmi
${arg2}parseArg故宫喵
${res}baidusearch${arg1}${arg2}
log many${res}

或是这样调用(多线程关键字是printer),需要导入一个内建库
** Settings **
Library Collections # 这里一定要注意大小写拼写

${li}Create List
:For${i}in range${4}
\${arg}parseArg循环线程${i}
\append to list${li}${arg}
${res}printer@{li}
log many${res}

需要注意的是,最后printer的时候需要@{li}而非${li}。@{li}本质上是解包,也就是相当于*args,把列表拆分成多个参数传入,而$会把列表当成一个整体传入

而multipleArg则要这样使用(关键字还是printer)

${arg}parseArg统一编号
${li}multipleArg${arg}${4}
${res}printer@{li}
log many${res}

这里一定要记得multipleArg后面要传数值格式的参数

多线程装饰器的代码实现如下

# coding: utf-8
from threading import Thread
# resset=[]  # 储存线程函数返回值的列表,这一句其实可以不要,因为在multiThread开启的时候会自动在外部创建全局变量resset为[](假如resset不存在,否则即赋值)

def getResult(func):  # 重定向函数返回的结果
    def infunc(*args,**kwargs):
        args=list(args)
        tid=args.pop()  # 去掉最后一个代表线程编号的参数
        args=tuple(args)
        try:
            resset.append((func(*args,**kwargs),tid))  # 结果是一个由二元元组组成的列表,每个线程一个元组,元组内第一个元素是线程运行的结果,第二个是线程编号
        except Exception,e:
            resset.append((e,tid))  # 如果线程内报错,就返回错误对象
    return infunc

def multiThread(func):  # 实现多线程
    def infunc(*args):
        global resset
        resset=[] # 每次调用前,清除结果集
        tli=[]  # 线程对象列表
        tid=0  # 初始线程编号
        for arg in args:  # 处理传入的参数列表
            if len(arg)==1:
                if type(arg[0])==type({}):
                    targ=()  # 设置位置参数
                    darg=arg[0]  # 设置命名参数
                else:
                    targ=arg[0]
                    darg={}
            elif len(arg)==0 or arg==None:
                targ=()
                darg={}
            else:
                targ=arg[0]  # (args,kwargs) [0]
                darg=arg[1]  # (args,kwargs) [1]
            try:
                assert type(targ)==type(()) and type(darg)==type({})  # 确定传来的参数格式正确
            except:
                raise ValueError, 'arguement format error'
            targ=tuple(list(targ)+[tid])  # 在位置参数的最后一个位置,加上线程编号传进去。getResult里会把这个参数pop掉,并记录到结果里
            tli.append(Thread(target=func,args=targ,kwargs=darg))  # 线程列表填充
            tid=tid+1  # 线程编号递增
        for th in tli:
            th.setDaemon(True)
            th.start()
        for th in tli:
            th.join()  # 大家都开始了才join阻塞
        return {x[1]:x[0] for x in resset}  # 结果字典,resset的结果是二元元组,0号元素是函数返回值,1号元素是线程编号tid

    return infunc

def parseArg(*args,**kwargs): # 打包单个线程的参数
    return (args,kwargs)

def multipleArg(gtuple,times): # 复制某个线程的参数n次,形成参数元组
    return (gtuple,)*times

####################################### 分割线,下为演示部分 #######################################

from selenium import webdriver
import time, re

@multiThread
@getResult
def baidusearch(statement):
    driver=webdriver.Chrome()
    driver.get(r'http://www.baidu.com')
    driver.maximize_window()
    driver.implicitly_wait(10)
    kw=driver.find_element_by_id('kw')
    kw.clear()
    kw.send_keys(statement)
    driver.find_element_by_id('su').click()
    time.sleep(2)
    resNumber=driver.find_element_by_xpath("//span[@class='nums_text']").text
    resNumber=re.findall('[0-9,]+',resNumber)[0]
    driver.close()
    return resNumber

li1=parseArg('mi')
li2=parseArg('wo')
li3=parseArg(u'故宫喵')
print(baidusearch(li1,li2,li3))

lis=multipleArg(parseArg('python'),3) # 或者可以像下面这样,连续生成多个同样的关键字
print(baidusearch(*lis))  # 这种方式不要忘记解包

lit=tuple([ parseArg('html'+str(x)) for x in range(1,6) ])  # 使用推导式,分别搜索html1 html2 ... html5
print(baidusearch(*lit))

################################# 可以使用路由的方式,让不同的函数并发执行 #######################

def plus(x,y):
    return x+y

def minus(x,y):
    return abs(x-y)

@multiThread
@getResult
def union(func_name,*args,**kwargs):  # 可以用这种方法来实现路由,让不同的函数同时执行在一个线程里
    return eval(func_name)(*args,**kwargs)

li1=parseArg('plus',1,2)
li2=parseArg('minus',3,y=5)
li3=parseArg('plus',x=4,y=6)
print(union(li1,li2,li3))

后记:这个方法当时并没有发现并不能支持类里的函数,所以有了改进版如下
https://blog.csdn.net/qq_27884799/article/details/89647075

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值