Python threading结合Selenium时,传入参数后线程串行运行而非并行的问题咨询
问题分析与解决方法
这是线程使用中非常典型的一个误区,我来帮你拆解问题根源和解决办法:
为什么改成target=test_logic(i)后变成串行?
当你写target=test_logic(i)时,你没有把函数对象传给线程,而是直接在主线程里执行了test_logic(i),并把这个函数的返回值(这里是None,因为函数没有return语句)赋值给了target。
也就是说,你的循环会先完整执行完一次test_logic(i),才会创建下一个线程,自然就变成了串行执行,完全失去了多线程并行的意义。
正确的传参方式
线程类threading.Thread提供了专门的参数来传递目标函数的参数,有两种常用的正确写法:
方法1:使用args参数(推荐)
把要传递的参数以元组的形式传给args参数,注意哪怕只有一个参数,元组末尾也要加逗号:
t = threading.Thread(name='Test {}'.format(i), target=test_logic, args=(i,))
方法2:使用lambda表达式包装
用lambda来创建一个匿名函数,间接调用你的目标函数:
# 注意:如果直接写lambda: test_logic(i),可能会因为循环变量延迟绑定导致所有线程用同一个i值 # 所以最好把i作为默认参数传入,避免这个问题 t = threading.Thread(name='Test {}'.format(i), target=lambda j=i: test_logic(j))
修正后的完整代码
from selenium import webdriver import threading import time def test_logic(j): driver = webdriver.Chrome() url = 'https://www.google.de' driver.get(url) # 这里可以添加你的测试逻辑 time.sleep(j) print(f'{threading.current_thread().name} 完成休眠,即将退出') driver.quit() N = 5 # 要启动的浏览器数量 thread_list = list() # 启动线程 for i in range(N): # 使用args传参的正确写法 t = threading.Thread(name='Test {}'.format(i), target=test_logic, args=(i,)) t.start() print(t.name + ' 已启动!') thread_list.append(t) # 等待所有线程执行完毕 for thread in thread_list: thread.join() print('所有测试已完成!')
关键总结
threading.Thread的target参数必须接收可调用的函数对象,而不是函数调用后的结果- 传递函数参数请优先使用
args/kwargs参数,这是线程模块设计的标准传参方式 - 如果用lambda包装,一定要注意循环变量的延迟绑定问题,避免出现意料之外的参数值
内容的提问来源于stack exchange,提问作者PDUY
相关产品推荐
相关产品推荐

