[英]Python How to run multiple functions every n seconds without interference
因此,假设我正在尝试使用 selenium 在网页上自动执行任务。
我有多个按钮需要点击,这会将我带到页面的不同部分,在那里我必须运行不同的功能来完成不同的任务。 每次点击这些按钮,当相应的任务完成后,一个计时器就会出现在按钮的位置。 当那个计时器用完时,我必须再次单击该按钮并运行任务的相应功能,然后冲洗并重复。
这是我试过的代码:
import selenium
import threading
driver = webdriver.Chrome()
driver.get("https://example.com")
def foo1():
button1 = driver.find_element_by_id("button1")
button1.click()
# do stuff
timer = int(button1.text)
threading.Timer(timer, foo1).start()
def foo2():
button2 = driver.find_element_by_id("button2")
button2.click()
# do stuff
timer = int(button2.text)
threading.Timer(timer, foo2).start()
def foo3():
button3 = driver.find_element_by_id("button3")
button3.click()
# do stuff
timer = int(button3.text)
threading.Timer(timer, foo3).start()
foo1()
foo2()
foo3()
现在,我的问题是,因为有多个这样的按钮,可能会出现其中一个计时器用完而另一个功能正在运行的情况。 这会导致脚本在没有完成当前任务序列的情况下点击离开,从而终止其中一个线程。
我试过使用 threading.Lock() 对象,但他们没有解决这个问题。 我有错误的方法还是我只是在这里遗漏了什么?
解决您的问题的最不痛苦的方法是使用多个 webdriver 对象,每个对象都在不同的线程中,并使用您想要传达的变量的字典。
import time
def foo():
driver = webdriver.Chrome()
driver.get("https://example.com")
button = driver.find_element_by_id("button")
while True:
button.click()
# do stuff
timer = int(button.text)
time.sleep(timer)
据我所知 webdriver 对象不是线程安全的,所以最好跨多个线程复制它,而不是在不同的线程中一遍又一遍地使用相同的对象。 同样在您的解决方案中,您会在每个不同的循环迭代中生成不同的线程,这可能会产生许多影响。 您可以在 C++ 中以类似情况查看此帖子
据我所知,可以改变线程初始化来解决问题。
import selenium
import threading
import time
driver = webdriver.Chrome()
driver.get("https://example.com")
def foo1():
button1 = driver.find_element_by_id("button1")
button1.click()
# do stuff
timer = int(button1.text)
time.sleep(timer)
foo1()
def foo2():
button2 = driver.find_element_by_id("button2")
button2.click()
# do stuff
timer = int(button2.text)
time.sleep(timer)
foo2()
t1 = threading.Thread(target=foo1)
t2 = threading.Thread(target=foo2)
t1.start()
t2.start()
您可以使用Lock
对象保持相同的代码结构。 但是,您只需定义一个Lock
对象并在每个函数中获取/释放它,如下所示:
import selenium
import threading
driver = webdriver.Chrome()
driver.get("https://example.com")
lock = threading.Lock()
def foo1():
lock.acquire()
button1 = driver.find_element_by_id("button1")
button1.click()
# do stuff
timer = int(button1.text)
lock.release()
threading.Timer(timer, foo1).start()
def foo2():
lock.acquire()
button2 = driver.find_element_by_id("button2")
button2.click()
# do stuff
timer = int(button2.text)
lock.release()
threading.Timer(timer, foo2).start()
def foo3():
lock.acquire()
button3 = driver.find_element_by_id("button3")
button3.click()
# do stuff
timer = int(button3.text)
lock.release()
threading.Timer(timer, foo3).start()
foo1()
foo2()
foo3()
通过这样做,您可以确保您的功能是原子的。 例如,如果foo2
在foo1
执行时被调用,那么一旦foo1
调用lock.release()
就会执行foo2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.