如何在Python脚本中获取由Bash脚本设置的环境变量?

3

我有一个名为setenv.sh的脚本,在许多脚本中都会在开头调用,其中大部分脚本都是bash脚本。很明显,这个脚本会设置一些环境变量,后面这些脚本会使用这些变量。

现在的问题是,我想在一些Python脚本中实现相同的行为,但我发现如果运行setenv,则Python脚本的环境不会更新。

由于我不想创建另一个脚本来先调用setenv.sh,再调用我的脚本(myscript.py)---我正在寻找一种方式来说服Python加载这些变量(解析seteve.h不是一个选项...因为它更复杂)。


2
你需要提供更多的细节,或者最好展示一下shell脚本。你是如何设置变量的?你是如何运行setenv.sh的?然后你是如何运行其他脚本的? - Daniel Roseman
我使用了 os.system() 来调用 setenv,但根据我的阅读,这并不重要,因为其他方法也会启动一个新进程,该进程将具有父进程(py)环境的副本。这意味着当子进程结束时,我将失去环境更改。当我从 bash 脚本中执行此操作时,它将起作用(只要它们使用 export = AAA=AAAVALUE)。 - sorin
3
执行外部脚本无法影响Python进程的环境。该脚本只能影响自己的环境,而不会影响生成它的Python进程的环境。 - chepner
@chepner...我的问题是如何从中获取这些变量...它们的值。一种丑陋的方法是执行"setenv.sh&echo VAR1"并解析输出...如果您需要加载大约10-15个变量,那么这种方法相当丑陋。 - sorin
3个回答

2

1
也许尝试在导出之前和之后运行env,然后比较结果。类似于这样的内容。
$ pwd
/tmp/test
$ cat setenv.sh
#!/bin/bash
export test=1234
$ cat test.sh
#!/bin/bash
source /tmp/test/setenv.sh
echo $test
$ ./test.sh
1234
$ python test.py
test=1234
$ cat test.py
#/usr/bin/env python
import os, subprocess
p=subprocess.Popen('env',stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
oldEnv=p.communicate()[0]
p=subprocess.Popen('source /tmp/test/setenv.sh ; env',stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
newEnv=p.communicate()[0]
for newStr in newEnv.split('\n'):
    flag = True
    for oldStr in oldEnv.split('\n'):
        if newStr == oldStr:
            #not exported by setenv.sh
            flag = False
            break
    if flag:
        #exported by setenv.sh
        print newStr

1
这显然会起作用...虽然不太美观,但应该能行。我会先测试一下。谢谢! - sorin
1
谢谢。我不得不接受另一个答案,因为它更简单,但你的答案也很好。 - sorin
1
没关系,Stack Overflow 上还有一些好的人,他们不仅仅关注声誉。我们提出问题和回答问题都只是因为我们可以 :-) - e271p314

1
最简单的解决方案显然是您不想要的,即为每个python脚本创建一个新的脚本文件。
但是,您可以通过让python脚本调用自身来实现大致相同的功能。当然,您需要向它发出信号,以免在第二次调用时执行该操作,否则您将得到无限(尾递归)。
以下这个小的“模块”(您可以直接导入,但应在启动之前立即执行,而不是其他任何操作之后)将检查环境变量SETENV是否已设置,如果是,则会重新发出python命令(尽力而为,因此如果它不是简单的脚本执行,则可能会出错)并在调用SETENV命名的文件后进行源代码处理。它缺少很多错误检查,不应被视为生产就绪;而是概念验证:
# file env_set.py
import os
import sys

if sys.argv[0] and "SETENV" in os.environ:
  setenv = os.environ["SETENV"]
  del os.environ["SETENV"]
  os.execvp("bash", ["bash", "-c",
        "source " + setenv + "; exec python " + sys.argv[0] + ' "${@}"',
        "--"] + sys.argv[1:])

还有一个小测试:

# file test_env_set.py
import env_set

import os
import sys
for name in sys.argv[1:]:
  if name in os.environ:
    print(name + "=" + os.environ[name])
  else:
    print("Undefined: " + name)

# file setenv.sh
export the_answer=42

$ python test_env_set.py SETENV the_answer
Undefined: SETENV
Undefined: the_answer
$ SETENV=setenv.sh python test_env_set.py SETENV the_answer
Undefined: SETENV
the_answer=42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接