Python多线程问题文件操作

Python多线程问题文件操作,python,multithreading,Python,Multithreading,我一直在尝试了解Python中多线程的诀窍。然而,每当我试图让它做一些可能被认为有用的事情时,我就会遇到问题 在本例中,我有300个PDF文件。为了简单起见,我们假设每个PDF上只有一个唯一的数字(比如1到300)。我试图让Python打开文件,从中获取文本,然后使用该文本相应地重命名文件 我制作的非多线程版本非常棒。但它有点慢,我想我会看看能不能把它加快一点。但是,此版本会找到第一个文件,正确重命名它,然后抛出一个错误,说明: FileNotFoundError: [Errno 2] No s

我一直在尝试了解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()
导入PyPDF2
导入操作系统
从操作系统导入listdir
从os.path导入isfile,加入
从PyPDF2导入PdfileWriter、PdfileReader
从multiprocessing.dummy导入池作为线程池
#全球的
i=0
def readPDF(所有文件):
打印(所有文件)
全球i
而我
是的,事实上,正如你所说,你已经把循环搞乱了。循环根本不应该存在。这是由
pool.map(…)
隐式处理的,它确保每个函数调用都会从列表中接收到一个唯一的文件名。你不应该做任何其他的循环

我已经在下面更新了您的代码,删除了循环和其他一些更改(我认为是一些小的改进):


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

是的,事实上,你已经把你说的循环搞乱了。循环根本不应该存在。这是由
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()