Python concurrent.futures для ускорения PyPDF2? - PullRequest
0 голосов
/ 06 ноября 2019

Я создал программу, которая будет искать во всех PDF-файлах, содержащихся в каталоге, слово или фразу. Если фраза найдена в заданном PDF, страница, содержащая этот термин, будет извлечена и сохранена как новый PDF.

Программа работает очень медленно. Мне нужно будет запустить более тысячи PDF-файлов, поэтому было бы очень полезно ускорить процесс, используя multiprocessing / concurrent.futures. Тем не менее, я просто не могу заставить все работать правильно.

Есть ли прямой способ включить многопроцессорность в приведенном ниже коде?

import PyPDF2
import re
import os
import glob
from pathlib import Path

String = input("Enter search string: ")
inputDir = Path(input("Enter path to directory containing PDFs to search: "))
outputDir = Path(input("Enter path to directory where you would like PDFs saved: "))
outputAppend = input("Text (including separator) to be appended to end of filenames (blank if none): ")
inputDir_glob = str(inputDir) + "/*.pdf"

PDFlist = sorted(glob.glob(inputDir_glob))

if not os.path.exists(str(outputDir)):
    os.makedirs(str(outputDir))


for filename in PDFlist:

    object = PyPDF2.PdfFileReader(filename, strict=False)

    # Get number of pages in the pdf
    NumPages = object.getNumPages()

    # Setup the file writer
    output = PyPDF2.PdfFileWriter()

    # Do the search
    for i in range(0, NumPages):
        PageObj = object.getPage(i)
        Text = PageObj.extractText()
        if re.search(String, Text):
            print("File: " + filename + "  |  " + "Page: " + str(i))
            output.addPage(object.getPage(i))
            outputStream = open(str(outputDir) + "/" + os.path.splitext(os.path.basename(filename))[0] + outputAppend + ".pdf", "wb")
            output.write(outputStream)
            outputStream.close()

1 Ответ

0 голосов
/ 06 ноября 2019

В итоге я понял это и подумал, что поделюсь, если кто-нибудь еще столкнется с подобной проблемой. Приведенное ниже решение значительно быстрее, чем оригинальный код (выложен выше):

import PyPDF2
import re
import os
import glob
from pathlib import Path
import concurrent.futures

# Enter the search term here:
String = input("Enter search string: ")

#Enter directory containing original PDFs:
inputDir = Path(input("Enter path to directory containing PDFs to search: "))
outputDir = Path(input("Enter path to directory where you would like PDFs saved: "))
outputAppend = input("Text (including separator) to be appended to end of filenames (blank if none): ")
inputDir_glob = str(inputDir) + "/*.pdf"

PDFlist = sorted(glob.glob(inputDir_glob))

if not os.path.exists(str(outputDir)):
    os.makedirs(str(outputDir))

def process_file(filename):
    object = PyPDF2.PdfFileReader(filename, strict=False)
    NumPages = object.getNumPages()
    output = PyPDF2.PdfFileWriter()

    # Do the search
    for i in range(0, NumPages):
        PageObj = object.getPage(i)
        Text = PageObj.extractText()
        if re.search(String, Text):
            print("File: " + filename + "  |  " + "Page: " + str(i))
            output.addPage(object.getPage(i))
            outputStream = open(str(outputDir) + "/" + os.path.splitext(os.path.basename(filename))[0] + outputAppend + ".pdf", "wb")
            output.write(outputStream)
            outputStream.close()
            #os.rename(filename, Path(str(outputDir) + "/Originals/" + str(os.path.basename(filename))))

with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    result = executor.map(process_file, (PDFlist))
...