簡體   English   中英

創建一個線程python隊列?

[英]Creating a threaded python queue?

我將如何創建隊列以在Python中在后台運行任務?

我嘗試過asyncio.Queue(),但每當我使用Queue.put(任務)時,它立即啟動任務。

它適用於在指定時間間隔內從數據庫接收未知數量的條目(文件名)的應用程序。 我希望用這個backgroundqueue實現的是python應用程序繼續運行並不斷返回新的文件名。 每次應用程序找到新的文件名時,都應該通過創建一個包含(方法(變量))的任務來處理它們。 這些任務都應該被拋入一個不斷擴展的隊列中,該隊列自己運行任務。 這是代碼。

class DatabaseHandler:
def __init__(self):
    try:
        self.cnx = mysql.connector.connect(user='root', password='', host='127.0.0.1', database='mydb')
        self.cnx.autocommit = True
        self.q = asyncio.Queue()
    except mysql.connector.Error as err:
        if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
            print("Something is wrong with your user name or password")
        elif err.errno == errorcode.ER_BAD_DB_ERROR:
            print("Database does not exist")
        else:
            print(err)
    self.get_new_entries(30.0)

def get_new_entries(self, delay):
    start_time = t.time()
    while True:
        current_time = datetime.datetime.now() - datetime.timedelta(seconds=delay)
        current_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
        data = current_time
        print(current_time)
        self.select_latest_entries(data)
        print("###################")
        t.sleep(delay - ((t.time() - start_time) % delay))

def select_latest_entries(self, input_data):
    query = """SELECT FILE_NAME FROM `added_files` WHERE CREATION_TIME > %s"""
    cursor = self.cnx.cursor()
    cursor.execute(query, (input_data,))
    for file_name in cursor.fetchall():
        file_name_string = ''.join(file_name)
        self.q.put(self.handle_new_file_names(file_name_string))
    cursor.close()

def handle_new_file_names(self, filename):
    create_new_npy_files(filename)
    self.update_entry(filename)

def update_entry(self, filename):
    print(filename)
    query = """UPDATE `added_files` SET NPY_CREATED_AT=NOW(), DELETED=1 WHERE FILE_NAME=%s"""
    update_cursor = self.cnx.cursor()
    self.cnx.commit()
    update_cursor.execute(query, (filename,))
    update_cursor.close()

正如我所說,這將立即執行任務。

create_new_npy_files是靜態類中非常耗時的方法。

這個表達式有兩個問題:

self.q.put(self.handle_new_file_names(file_name_string))

首先,它實際上是調用 handle_new_file_names方法並將其結果 handle_new_file_names 這不是特定於asyncio.Queue ,它是函數調用在Python(以及大多數主流語言)中的工作方式。 以上相當於:

_tmp = self.handle_new_file_names(file_name_string)
self.q.put(_tmp)

第二個問題是像getput這樣的asyncio.Queue操作是協同程序 ,所以你必須等待它們。

如果要將可調用隊列入隊列,可以使用lambda

await self.q.put(lambda: self.handle_new_file_names(file_name_string))

但由於隊列的使用者在您的控制之下,您可以簡單地將文件名排入隊列,如@dirn所示:

await self.q.put(file_name_string)

隊列的使用者將使用await self.q.get()來讀取文件名並在每個上調用self.handle_new_file_names()

如果您打算使用asyncio,請考慮閱讀涵蓋基礎知識的教程 ,並切換到符合asyncio的數據庫連接器,以便數據庫查詢與asyncio事件循環一起播放。

對於將來看到這一點的人。 我標記為接受的答案是如何解決問題的解釋。 我會寫下一些我用來創建我想要的代碼。 也就是說,應該在后台運行的任務。 干得好。

from multiprocessing import Queue
import threading

class ThisClass
    def __init__(self):
        self.q = Queue()
        self.worker = threading.Thread(target=self._consume_queue)
        self.worker.start()
        self.run()

創建的隊列不是任務的隊列,而是您要處理的變量。

def run(self):
    for i in range(100):
        self.q.put(i)

然后是_consume_queue() ,當有項目時,它會消耗隊列中的項目:

def _consume_queue(self):
    while True:
        number = self.q.get()
        # the logic you want to use per number.

似乎self.q.get()等待新條目,即使沒有條目也是如此。

上面的-simplified-代碼對我有用,我希望它也適用於其他人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM