Как установить shell = True для Subprocess.run с исполнителем concurrent.future Pool Threading - PullRequest
0 голосов
/ 05 июня 2019

Я пытаюсь использовать многопоточность concurrent.future в Python с subprocess.run для запуска внешнего скрипта Python.Но у меня есть некоторые проблемы с частью shell=True в subprocess.run ().

Вот пример внешнего кода, назовем его test.py:

#! /usr/bin/env python3

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-x', '--x_nb', required=True, help='the x number')
    parser.add_argument('-y', '--y_nb', required=True, help='the y number')
    args = parser.parse_args()

    print('result is {} when {} multiplied by {}'.format(int(args.x_nb) * int(args.y_nb),
                                                         args.x_nb,
                                                         args.y_nb))

В моем основном скрипте Python у меня есть:

#! /usr/bin/env python3

import subprocess
import concurrent.futures
import threading
...

args_list = []
for i in range(10):
    cmd = './test.py -x {} -y 2 '.format(i)
    args_list.append(cmd)

# just as an example, this line works fine
subprocess.run(args_list[0], shell=True)

# this multithreading is not working       
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    executor.map(subprocess.run, args_list)

Проблема здесь в том, что я не могу передать опцию shell=True в executor.map.

Я уже пытался без успеха:

args_list = []
for i in range(10):
    cmd = './test.py -x {} -y 2 '.format(i)
    args_list.append((cmd, eval('shell=True'))

или

args_list = []
for i in range(10):
    cmd = './test.py -x {} -y 2 '.format(i)
    args_list.append((cmd, 'shell=True'))

У кого-нибудь есть идеи, как решить эту проблему?

1 Ответ

1 голос
/ 07 июня 2019

Я не думаю, что метод map может вызывать функцию с аргументами ключевых слов напрямую, но есть 2 простых решения вашей проблемы.

Решение 1. Используйте лямбду, чтобы задать дополнительный аргумент ключевого слова, который выwant

Лямбда - это небольшая функция, которая вызывает вашу реальную функцию, передавая аргументы.Это хорошее решение, если ключевые аргументы являются фиксированными.

with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    executor.map(lambda args: subprocess.run(args, shell=True), args_list)

Решение 2. Используйте executor.submit для отправки функций исполнителю

Метод submit позволяет указать аргументыи ключевые аргументы для целевой функции.

with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
    for args in args_list:
        executor.submit(subprocess.run, args, shell=True)
...