Почему вызов grep с использованием subprocess.Popen() значительно быстрее, чем с использованием subprocess.check_output()

#python #time #grep #subprocess

#python #время #grep #подпроцесс

Вопрос:

Мне нужно извлечь строки записей в файл, подобный csv, и я использую grep для выполнения этого внутри скрипта python. Я заметил, что когда я вызываю grep с использованием subprocess.check_output, для завершения требуется около 5,28 секунд. Но когда я использую subprocess.Popen, это занимает всего 0,002 секунды. Кажется, это огромная разница, и мне интересно, какой из них мне следует использовать. Следует отметить, что я намерен обрабатывать каждую строку как строку.

Вот часть моего скрипта на python.

 myenv = os.environ.copy()
myenv['LC_ALL'] = 'C'
file = data_path '/' files[12]
start = time.time()
match = 'chr3'   "[[:space:]]"
matched_reads = subprocess.Popen(['grep', match, file], stdout=subprocess.PIPE, env=myenv)
mathced_reads = str(matched_reads).splitlines()
end = time.time()
runtime = end-start
print("Popen Grep: ", runtime)

start = time.time()
match = 'chr3'   "[[:space:]]"
matched_reads = subprocess.check_output(['grep', match, file],env=myenv)
mathced_reads = str(matched_reads).splitlines()
end = time.time()
runtime = end-start
print("Checkoutput Grep: ", runtime)
  

Ответ №1:

Вы обнаружите, что вызов Popen фактически не выполняет программу и не возвращает выходные данные, а скорее создает объект, который ссылается на созданный процесс. В вашем случае вы не вызывали, Popen.communicate который «общается» с процессом и завершает его вывод. Тогда как check_output делает все это за вас. Вы обнаружите, что communicate метод займет примерно столько же времени, но фактически вернет желаемый результат.

Для фактической демонстрации с POpen замените

 matched_reads = subprocess.Popen(['grep', match, file], stdout=subprocess.PIPE, env=myenv)
  

с

 process = subprocess.Popen(['grep', match, file], stdout=subprocess.PIPE, env=myenv)
matched_reads, stderr = process.communicate()
  

Который должен воспроизводить то же поведение, что и check_output для того, чтобы matched_reads содержать выходные данные, созданные grep .