繁体   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