RF本身沒有多線程的庫,我們可以使用類似下面的方法,並對外公開parseArg和multipleArg兩個方法(寫到測試類裏面),給需要併發的函數套上裝飾器,即可實現多線程執行函數。由於可以只傳單個的參數,因此並不影響函數的單線程運行。
比如在RIDE/RED內可以寫成這樣的調用
${arg1} | parseArg | mi | |
${arg2} | parseArg | 故宮喵 | |
log many | baidusearch | ${arg1} | ${arg2} |
# 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))