[英]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)
第二個問題是像get
和put
這樣的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.