在Python中模拟Bash“source”

2024-04-25 10:15:38 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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


Tags: name功能env脚本iffooinitvalue
3条回答

您的方法的问题在于您试图解释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

有关详细信息,请阅读subprocess上的文档。

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

享受吧。

注意Python documentation表示,如果要操作环境,应该直接操作os.environ,而不是使用os.putenv()。我认为那是个错误,但我离题了。

使用泡菜:

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,subprocess,并显式地使用/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

与其让Python脚本为bash脚本提供源代码,不如使用包装脚本源init_env,然后使用修改后的环境运行Python脚本。

#!/bin/bash
source init_env
/run/python/script.py

相关问题 更多 >