簡體   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