【问题标题】:How to set shell=True for a Subprocess.run with a concurrent.future Pool Threading Executor如何使用 concurrent.future 池线程执行器为 Subprocess.run 设置 shell=True
【发布时间】:2019-06-05 16:12:29
【问题描述】:

我尝试在 Python 中使用 concurrent.future 多线程和 subprocess.run 来启动外部 Python 脚本。但是我对 subprocess.run() 的 shell=True 部分有一些麻烦。

这是一个外部代码的例子,我们称之为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'))

有人知道如何解决这个问题吗?

【问题讨论】:

    标签: python-3.x multithreading subprocess concurrent.futures


    【解决方案1】:

    我不认为map 方法可以直接调用带有关键字 args 的函数,但有 2 个简单的解决方案可以解决您的问题。

    解决方案 1:使用 lambda 设置所需的额外关键字参数

    lambda 基本上是一个小函数,它调用你的真实函数,传递参数。如果关键字参数是固定的,这是一个很好的解决方案。

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

    方案二:使用 executor.submit 将函数提交给 executor

    submit 方法允许您为目标函数指定 args 和关键字 args。

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

    【讨论】:

    • 非常感谢马克!您使用循环和submit 的解决方案工作得很好。我也尝试了lambda 函数,但我的情况比示例复杂一点,但我无法达到我想要的结果。
    猜你喜欢
    • 1970-01-01
    • 2014-08-27
    • 2017-12-29
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多