首页 > 解决方案 > Python多线程问题文件操作

问题描述

我一直在尝试掌握 Python 中的多线程。然而,每当我试图让它做一些可能被认为有用的事情时,我都会遇到问题。

在这种情况下,我有 300 个 PDF 文件。为简单起见,我们假设每个 PDF 上只有一个唯一编号(例如 1 到 300)。我试图让 Python 打开文件,从中获取文本,然后使用该文本相应地重命名文件。

我制作的非多线程版本效果惊人。但它有点慢,我想我会看看我是否可以加快一点。然而,这个版本找到了第一个文件,正确地重命名它,然后抛出一个错误说:

FileNotFoundError: [Errno 2] No such file or directory: './pdfPages/1006941.pdf'

它基本上告诉我它找不到该名称的文件。它不能的原因是它已经命名了它。在我的脑海里,这告诉我,我可能已经把这个循环和/或多线程搞砸了。

任何帮助,将不胜感激。

来源:

import PyPDF2
import os
from os import listdir
from os.path import isfile, join
from PyPDF2 import PdfFileWriter, PdfFileReader
from multiprocessing.dummy import Pool as ThreadPool 
# Global
i=0

def readPDF(allFiles):
    print(allFiles)
    global i
    while i < l:
        i+=1
        pdf_file = open(path+allFiles, 'rb')
        read_pdf = PyPDF2.PdfFileReader(pdf_file)
        number_of_pages = read_pdf.getNumPages()
        page = read_pdf.getPage(0)
        page_content = page.extractText()
        pdf_file.close()
        Text = str(page_content.encode('utf-8')).strip("b").strip("'")
        os.rename(path+allFiles,path+pre+"-"+Text+".PDF")       

pre = "77"
path = "./pdfPages/"
included_extensions = ['pdf','PDF']
allFiles = [f for f in listdir(path) if any(f.endswith(ext) for ext in included_extensions)] # Get all files in current directory
l = len(allFiles)

pool = ThreadPool(4)

doThings = pool.map(readPDF, allFiles)

pool.close()
pool.join()

标签: pythonmultithreading

解决方案


是的,事实上,正如你所说,你已经搞砸了循环。循环根本不应该存在。这是由 隐式处理的pool.map(...),确保每个函数调用都会从您的列表中接收一个唯一的文件名以供使用。你不应该做任何其他循环。

我已经通过删除循环和其他一些更改(我认为很小,但仍有改进)更新了您的代码:

# Removed a number of imports
import PyPDF2
import os
from multiprocessing.dummy import Pool as ThreadPool 

# Removed not needed global variable

def readPDF(allFiles):
    # The while loop not needed, as pool.map will distribute the different
    # files to different processes anyway
    print(allFiles)
    pdf_file = open(path+allFiles, 'rb')
    read_pdf = PyPDF2.PdfFileReader(pdf_file)
    number_of_pages = read_pdf.getNumPages()
    page = read_pdf.getPage(0)
    page_content = page.extractText()
    pdf_file.close()
    Text = str(page_content.encode('utf-8')).strip("b").strip("'")
    os.rename(path+allFiles,path+pre+"-"+Text+".PDF")       

pre = "77"
path = "./pdfPages/"
included_extensions = ('pdf','PDF') # Tuple instead of list

# Tuple allows for simpler "F.endswith"
allFiles = [f for f in os.listdir(path) if f.endswith(included_ext)]

pool = ThreadPool(4)

doThings = pool.map(readPDF, allFiles)
# doThings will be a list of "None"s since the readPDF returns nothing

pool.close()
pool.join()

因此,不需要全局变量和计数器,因为所有这些都是隐式处理的。但是,即使进行了这些更改,也不能肯定这会大大加快您的执行速度。很可能,程序执行的大部分时间都在等待磁盘加载。在这种情况下,即使您有多个线程,它们仍然可能必须等待主要资源,即硬盘驱动器。但是要确定,您必须进行测试。


推荐阅读