[英]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.