Почему подпроцесс Python намного медленнее использует .PIPE и stdout? - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть код, использующий concurrent.futures, который выполняет al oop параллельно. Каждый проход l oop основан на итерации пары значений ключа словаря. Для каждого прохода l oop исполняемый файл запускается с использованием подпроцесса:

import concurrent.futures
import traceback
import sys
import os
import subprocess
import time
from datetime import datetime

global sub_dict

sub_dict = {
    1: 'one',
    2: 'two',
    3: 'three',
    4: 'four',
    5: 'five',
    6: 'six',
    7: 'seven',
    8: 'eight',
    #
    9: 'nine',
    10: 'ten',
    11: 'eleven',
    12: 'twelve',
    13: 'thirteen',
    14: 'fourteen',
    15: 'fifteen',
    16: 'sixteen',
    #
    17: 'seventeen',
    18: 'eighteen',
    19: 'nineteen',
    20: 'twenty',
    21: 'twenty one',
    22: 'twenty two',
    23: 'twenty three',
    24: 'twenty four'
}

start_time = datetime.now()

def test_func(new_dict, i):

    try:

        new_dict2 = {}
        new_dict2.update({new_dict[0] : new_dict[1]})

        for key, value in new_dict2.items():

            startupinfo = None
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW



            exe_string1 = "C:\\Users\\Oleg Salenko\\AppData\\Local\\WebGrab+Plus\\Addons\\Scraper Outputs\\Grabber 1\\WebGrab+Plus\\bin\\WebGrab+Plus.exe"

            '''Uncomment to not pipe'''
            #process = subprocess.Popen([exe_string1])

            '''Comment out the next five lines to run without pipe'''
            process = subprocess.Popen([exe_string1], stdout=subprocess.PIPE, startupinfo=startupinfo)

            process2 = process.pid
            streamdata = process.communicate()[0]
            streamdata2 = streamdata.decode(errors='replace')
            rc = process.returncode

            process.wait(timeout = 30)
            process.terminate()


            '''Different return values base on run type'''
            return key, value, process2, streamdata2, rc
            #return key, value

    except Exception as exc:

        print('%r generated an exception: %s' % (new_dict2, exc))



def concurrent_func():

    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:

        future_to_pair = {executor.submit(test_func, v, i): (i, v) for i, v in enumerate(sub_dict.items(), 1)}

        for future in concurrent.futures.as_completed(future_to_pair):

            pair = future_to_pair[future]

            try:

                data = future.result()

            except Exception as exc:

                print('%r generated an exception: %s' % (pair, exc))

            else:

                print(data)
                print('-' * 150)
                print('-' * 150)
                print('-' * 150)

concurrent_func()

end_time = datetime.now()

total_time = end_time - start_time
print(total_time)

Я протестировал запуск этого как с использованием PIPE и stdout, так и без:

С: 0:01:18.823474 Без : 0:00:30.178876

.. как вы можете видеть, это намного, намного быстрее, без использования PIPE и stdout. Может кто-нибудь объяснить, почему это так и то, что я мог бы изменить, если что-нибудь в коде, чтобы сохранить вывод из оболочки, который моя Python программа может использовать в нисходящем направлении?

Спасибо

...