为了账号安全,请及时绑定邮箱和手机立即绑定

在Python中模拟Bash“源”

/ 猿问

在Python中模拟Bash“源”

倚天杖 2019-11-12 10:19:21

我有一个脚本,看起来像这样:


export foo=/tmp/foo                                          

export bar=/tmp/bar

每次构建时,我都会运行“ source init_env”(其中init_env是上面的脚本)来设置一些变量。


为了在Python中完成同样的工作,我运行了这段代码,


reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')

for line in open(file):

    m = reg.match(line)

    if m:

        name = m.group('name')

        value = ''

        if m.group('value'):

            value = m.group('value')

        os.putenv(name, value)

但是后来有人决定将以下行添加到init_env文件中会很好:


export PATH="/foo/bar:/bar/foo:$PATH"     

显然我的Python脚本崩溃了。我可以修改Python脚本来处理这一行,但是稍后当有人想出要在init_env文件中使用的新功能时,它将中断。


问题是,是否有一种简单的方法来运行Bash命令并让其修改我的os.environ?


查看完整描述

3 回答

?
慕桂英4014372

您的方法存在的问题是您正在尝试解释bash脚本。首先,您只是尝试解释导出语句。然后您会发现人们正在使用变量扩展。以后人们将条件文件放入他们的文件中,或处理替代文件。最后,您将获得功能齐全的bash脚本解释器,其中包含大量错误。不要那样做


让Bash为您解释文件,然后收集结果。


您可以这样做:


#! /usr/bin/env python


import os

import pprint

import shlex

import subprocess


command = shlex.split("env -i bash -c 'source init_env && env'")

proc = subprocess.Popen(command, stdout = subprocess.PIPE)

for line in proc.stdout:

  (key, _, value) = line.partition("=")

  os.environ[key] = value

proc.communicate()


pprint.pprint(dict(os.environ))

确保处理错误,以防bash失败source init_env,bash本身无法执行,子进程无法执行bash或任何其他错误。


将env -i在命令行的开始创造一个清洁的环境。这意味着您只能从中获取环境变量init_env。如果要继承的系统环境,请省略env -i。


请阅读有关子流程的文档,以获取更多详细信息。


注意:这将仅捕获使用export语句设置的变量,因为env仅打印导出的变量。


请享用。


请注意,Python文档指出,如果要操作环境,则应os.environ直接操作而不是使用os.putenv()。我认为是一个错误,但我离题了。


查看完整回答
反对 回复 2019-11-12
?
慕仰1329654

使用泡菜:


import os, pickle

# For clarity, I moved this string out of the command

source = 'source init_env'

dump = '/usr/bin/python -c "import os,pickle;print pickle.dumps(os.environ)"'

penv = os.popen('%s && %s' %(source,dump))

env = pickle.loads(penv.read())

os.environ = env

更新:


这使用json,子进程,并显式使用/ bin / bash(用于ubuntu支持):


import os, subprocess as sp, json

source = 'source init_env'

dump = '/usr/bin/python -c "import os, json;print json.dumps(dict(os.environ))"'

pipe = sp.Popen(['/bin/bash', '-c', '%s && %s' %(source,dump)], stdout=sp.PIPE)

env = json.loads(pipe.stdout.read())

os.environ = env


查看完整回答
反对 回复 2019-11-12
?
慕姐4208626

将@Brian的出色答案包装在函数中的示例:


import json

import subprocess


# returns a dictionary of the environment variables resulting from sourcing a file

def env_from_sourcing(file_to_source_path, include_unexported_variables=False):

    source = '%ssource %s' % ("set -a && " if include_unexported_variables else "", file_to_source_path)

    dump = '/usr/bin/python -c "import os, json; print json.dumps(dict(os.environ))"'

    pipe = subprocess.Popen(['/bin/bash', '-c', '%s && %s' % (source, dump)], stdout=subprocess.PIPE)

    return json.loads(pipe.stdout.read())

我正在使用此实用程序功能来读取AWS凭证和docker .env文件include_unexported_variables=True。


查看完整回答
反对 回复 2019-11-12

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信