Многопроцессорная Python 3 - PullRequest
       20

Многопроцессорная Python 3

0 голосов
/ 21 января 2020

Я пытался создать многопроцессорный пул для серии задач на python 3. Задачи заключаются в следующем: 1. Чтение через pdf-файлы и захват таблиц в pdf-файле, а затем - 2. Создание Файл pickle для хранения объектов таблицы 3. Загрузка файлов pickle

Я запустил код python в режиме сериализации, а также распараллеливания для трех файлов PDF для тестирования. Секвенирование запускает весь процесс за 200 секунд и создает файлы pickle в рабочем каталоге. Тем не менее, многопроцессорная обработка не генерирует файлы рассылки в каталоге, но для запуска процесса требуется 39 секунд.

Код последовательности можно найти ниже:

os.chdir('C:/Users/dir_path')

    def process_table(pdf):
        for pdf in pdfs:
            tables = camelot.read_pdf(pdf, pages = 'all', flag_size=True, copy_text=['v'], line_scale=40) 
            print(f'Process {os.getpid()} Processing File Name:{pdf}\nTotal Tables found:{len(tables)}')
            with open(pdf.split('.pdf')[0] + '.pkl', 'wb') as f:
                pickle.dump(tables, f)
                print(f'Process {os.getpid()} Pickle file created for: {pdf}')
            with open(pdf.split('.pdf')[0] + '.pkl', 'rb') as g:
                pickle.load(g)
                print(f'Process {os.getpid()} Pickle file loaded: {pdf}')

    def process_handler():    
        start_time = time.time()
        pdfs = [file_name for file_name in os.listdir()]
        process_table(pdfs)
        end = time.time()
        duration = round(time.time() - start_time)
        print(f'Whole Process completed in {duration} second(s)') 


if __name__ == '__main__':
    process_handler()    

Вывод код ниже:

Выход сериализации Код для многопроцессорной обработки приведен ниже:

os.chdir('C:/Users/dir_path')

def process_table(pdf):
        tables = camelot.read_pdf(pdf, pages = 'all', flag_size=True, copy_text=['v'], line_scale=40) 
        print(f'Process {os.getpid()} Processing File Name:{pdf}\nTotal Tables found:{len(tables)}')
        with open(pdf.split('.pdf')[0] + '.pkl', 'wb') as f:
            pickle.dump(tables, f)
            print(f'Process {os.getpid()} Pickle file created for: {pdf}')
        with open(pdf.split('.pdf')[0] + '.pkl', 'rb') as g:
            pickle.load(g)
            print(f'Process {os.getpid()} Pickle file loaded for: {pdf}')

def process_handler():    
    start_time = time.time()

    files = [file_name for file_name in os.listdir()]
    with ThreadPoolExecutor() as executor:
        executor.map(process_table, files)

    duration = round(time.time() - start_time)
    print(f'Whole Process completed in {duration} second(s)') 

if __name__ == '__main__':
    process_handler()

Буду очень признателен за ценный отзыв об этом. Это очень важно, потому что иногда PDF-файл размером 20 МБ занимает очень много времени для преобразования в файл pickle с сохраненными в них объектами таблицы. Следовательно, процесс застревает на первом задании (то есть в формате PDF размером 20 МБ) и не может перейти к следующему заданию, пока не завершится первое.

Спасибо

1 Ответ

0 голосов
/ 21 января 2020

Несколько предметов;

  • Я использовал только тот пул многопроцессорной обработки, который, как мне показалось, работает достаточно хорошо.
  • process_table вызывается с помощью pdfs вне функции карты, поэтому выполняется в последовательном режиме.
  • work_items не содержит ничего, насколько я могу судить, кроме из None.
  • Вы вызываете process_table с аргументом списка (pdf), но затем используете глобальную переменную pdfs.

Я бы предложил что-то вроде;

import multiprocessing as mp

files = [file_name for file_name in os.listdir()]
with mp.Pool(mp.cpu_count()-1) as pool:
    pool.map(files, process_table)
...