繁体   English   中英

Python如何在不干扰的情况下每n秒运行多个函数

[英]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()

通过这样做,您可以确保您的功能是原子的。 例如,如果foo2foo1执行时被调用,那么一旦foo1调用lock.release()就会执行foo2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM