【问题标题】:Python - subprocess and the env argumentPython - 子进程和 env 参数
【发布时间】:2020-02-05 11:30:02
【问题描述】:

我正在完成一个项目,我只剩下一件事要做; 寻找一种优雅的方式来使用subprocess 启动程序,包括自定义环境变量集。

猫脚本.py

#!/usr/bin/env python

import argparse
import subprocess
import sys
import os

parser = argparse.ArgumentParser()

parser.add_argument(
                    action='store',
                    nargs='*',
                    dest="foovar"
                    )

parser.add_argument('-a', action='store',
                    type=int,
                    default='43',
                    dest="var_version",
                    help='set the agent version to use. default:(4)')

parser.add_argument('-s', action='store',
                    type=int,
                    default='35',
                    dest="var_server",
                    help='set the version. default:(5)')

args = parser.parse_args()

sub_env = os.environ.copy()
for key in vars(args):
    if key.startswith('var_'):
        sub_env[key] = vars(args)[key]

print(vars(args))
print(args)   # Namespace(foovar=['james', 'marc'], var_version=43, var_server=35)

for machine in args.foovar:
        exit_code = subprocess.call("bash script.sh %s" % machine, env=sub_env, shell=True)

这里是 script.sh

#!/bin/bash

if [[ $(printenv | grep 'var_') ]]; then
        echo "var_* is working!"
fi

这里是输出:

$ ./script.py james marc -a 43 -s 35
{'var_version': 43, 'foovar': ['james', 'marc'], 'var_server': 35}
Namespace(foovar=['james', 'marc'], var_server=35, var_version=43)
Traceback (most recent call last):
  File "./script.py", line 44, in <module>
    exit_code = subprocess.call("bash script.sh %s" % machine, env=sub_env, shell=True)
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
TypeError: execve() arg 3 contains a non-string value

nb:此帖子已根据评论建议进行了更新。

【问题讨论】:

  • var(args)['foovar'] 是一种相当丑陋的写法args.foovar
  • subprocess.Popen 返回一个进程,而不是退出状态。您需要自己管理流程,或者,如果您只想等待子流程,请切换到subprocess.run。您还可以通过将字符串转换为列表来避免愚蠢的shell=True['bash', 'script.sh', machine]。或许也可以看看stackoverflow.com/questions/4256107/…

标签: python bash subprocess


【解决方案1】:

您的参数 var_version=43var_server=35 是 Python 整数。您需要将它们转换为字符串才能将它们传递给子进程。

sub_env = os.environ.copy()
for key in vars(args):
    if key.startswith('var_'):
        sub_env[key] = str(getattr(args, key))

【讨论】:

    【解决方案2】:

    env 参数传递给subprocess 函数(在您的情况下为Popen)。要修改调用进程的环境,请复制os.environ。例如:

    sub_env = os.environ.copy()
    for key in vars(args):
        if key.startswith('var_'):
            sub_env[key] = args[key]
    for machine in vars(args)['foovar']:
        exit_code = subprocess.Popen("…", env=sub_env, …)
    

    【讨论】:

    • 我得到一个类型错误。 中的文件“./script.py”第 34 行,用于 args 中的键:TypeError: 'Namespace' object is not iterable .
    • @nerabis 哦,对了,这是一个Namespace,所以你需要vars(args) 来迭代它。无论如何,这只是一个示例,重点是您复制 os.environ 并向其中添加(或删除)内容。
    • 我编辑了帖子 - 感谢您的建议。不知道为什么会得到:TypeError: execve() arg 3 contains a non-string value
    猜你喜欢
    • 2012-07-25
    • 2018-07-30
    • 2012-10-31
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    相关资源
    最近更新 更多