在 Python 中模拟 Bash“源" [英] Emulating Bash 'source' in Python

查看:13
本文介绍了在 Python 中模拟 Bash“源"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a script that looks something like this:

export foo=/tmp/foo                                          
export bar=/tmp/bar

每次构建时,我都会运行source init_env"(其中 init_env 是上述脚本)来设置一些变量.

Every time I build I run 'source init_env' (where init_env is the above script) to set up some variables.

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

To accomplish the same in Python I had this code running,

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文件中添加如下一行:

But then someone decided it would be nice to add a line like the following to the init_env file:

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

显然我的 Python 脚本崩溃了.我可以修改 Python 脚本来处理这一行,但是当 someone 提出要在 init_env 文件中使用的新功能时,它就会中断.

Obviously my Python script fell apart. I could modify the Python script to handle this line, but then it'll just break later on when someone comes up with a new feature to use in the init_env file.

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

The question is if there is an easy way to run a Bash command and let it modify my os.environ?

推荐答案

你的方法的问题在于你试图解释 bash 脚本.首先,您只是尝试解释导出语句.然后你注意到人们正在使用变量扩展.后来人们会将条件放在他们的文件中,或处理替换.最后,您将拥有一个完整的 bash 脚本解释器,其中包含大量错误.不要那样做.

The problem with your approach is that you are trying to interpret bash scripts. First you just try to interpret the export statement. Then you notice people are using variable expansion. Later people will put conditionals in their files, or process substitutions. In the end you will have a full blown bash script interpreter with a gazillion bugs. Don't do that.

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

Let Bash interpret the file for you and then collect the results.

你可以这样做:

#! /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,或任何其他错误.

Make sure that you handle errors in case bash fails to source init_env, or bash itself fails to execute, or subprocess fails to execute bash, or any other errors.

命令行开头的 env -i 创建一个干净的环境.这意味着您只能从 init_env 获取环境变量.如果您想要继承的系统环境,则省略 env -i.

the env -i at the beginning of the command line creates a clean environment. that means you will only get the environment variables from init_env. if you want the inherited system environment then omit env -i.

阅读有关子进程的文档了解更多详情.

Read the documentation on subprocess for more details.

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

Note: this will only capture variables set with the export statement, as env only prints exported variables.

享受.

请注意,Python 文档 说,如果您想操作您应该直接操作 os.environ 而不是使用 os.putenv() 的环境.我认为这是一个错误,但我离题了.

Note that the Python documentation says that if you want to manipulate the environment you should manipulate os.environ directly instead of using os.putenv(). I consider that a bug, but I digress.

这篇关于在 Python 中模拟 Bash“源"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆