Python多线程未正确从队列中获取

Posted

技术标签:

【中文标题】Python多线程未正确从队列中获取【英文标题】:Python MultiThreading Not Taking From Queue Properly 【发布时间】:2021-12-14 04:12:17 【问题描述】:

我正在同时解析大量文档,为此我集成了一个包含文档列表的队列,之后我分配线程以通过 pdf 文件运行解析到队列中空它应该返回我的结果,但是当我输出队列的大小很多时候即使多个线程正在运行它输出相同的数字意味着一些线程得到相同的pdf,我相信我的系统效率低下与线程并希望任何输入以使此解析和运行更快,这是我当前的代码。

    def searchButtonClicked(self):
        name = self.lineEdit.text()
        self.listWidget.addItem("Searching with the name: " + name)
        num_threads = 35
        try:
            with open("my_saved_queue.obj","rb") as queue_save_file:
                self.my_loaded_list: Queue = pickle.load(queue_save_file)
                self.my_loaded_queue = queue.Queue()
                for row in self.my_loaded_list:
                    self.my_loaded_queue.put(row)
                for i in range(num_threads):
                    worker = threading.Thread(target=self.searchName, args=(name,))
                    worker.setDaemon(True)
                    worker.start()
        except:
            self.saveFile()
            self.searchButtonClicked()

    def saveFile(self):
        my_queue = list()
        for root, dirs, files in os.walk(self.directory):
            for file_name in files:
                file_path = os.path.join(root, file_name)
                if file_path.endswith(".pdf"):
                    my_queue.insert(0,[PyPDF2.PdfFileReader(file_path, strict=False), file_path])
        with open("my_saved_queue.obj","wb+") as queue_save_file:
            pickle.dump(my_queue, queue_save_file)

    def searchName(self, name):
        try:
            queue_obj = self.my_loaded_queue.get(False)
        except Empty:
            self.my_loaded_queue.task_done()
            self.listWidget.addItem("---------------Done---------------")
        else:
            pdf_object = queue_obj[0]
            file_path = queue_obj[1]
            num_of_pages = pdf_object.getNumPages()

            for i in range(0, num_of_pages):
                PageObj = pdf_object.getPage(i)
                Text = PageObj.extractText() 
                ResSearch = re.search(name, Text)
                if(ResSearch):
                    print(file_path + " Page " + str(i+1))
                    self.listWidget.addItem(file_path + " Page" + str(i+1))
                    continue
                else:
                    continue
            print(self.my_loaded_queue.qsize())
            if not self.my_loaded_queue.empty():
                self.searchName(name)

    def clearListWidget(self):
        self.listWidget.clear()

基本上我解析目录并将所有 pdf 存储到一个列表中,然后我将其保存回目录以在搜索名称时访问,这样可以节省时间并且我不必解析所有 pdf。这是在 searchName() 底部输出 qsize 时的输出:

正如我们所看到的,有时它会多次输出大小,这意味着多个线程,即使一开始我们正在离开队列的顶部,这应该删除一些大小。

【问题讨论】:

【参考方案1】:

这很正常。

这可能会按以下顺序发生:

线程 1 从队列中获取一个对象。 线程 2 从队列中获取对象 线程 2 打印尺寸 线程 1 打印大小

但这不是问题。该程序可以很好地运行。

【讨论】:

知道了,目前它需要很长时间才能解析,一个名称大约需要 15-20 分钟,大约需要 5 gigs 的数据,所以这听起来对吗?

以上是关于Python多线程未正确从队列中获取的主要内容,如果未能解决你的问题,请参考以下文章

Python 多线程同步队列模型

Python多线程编程

Python的多线程锁跟队列

多线程Python进程,队列和锁相关的一些问题

Python多线程中队列到底是个啥概念?

Python3 -- 多线程(threading模块queue模块)