繁体   English   中英

从 python 脚本导入 bash 变量

[英]Import bash variables from a python script

我已经看到很多从 bash 脚本内部运行 python 脚本的例子,或者将变量作为参数传递或使用导出来授予子 shell 访问权限,但我在这里尝试做相反的事情。

我正在运行一个 python 脚本并有一个单独的文件,我们称之为 myGlobalVariables.bash

myGlobalVariables.bash:

foo_1="var1"    
foo_2="var2"   
foo_3="var3"  

我的 python 脚本需要使用这些变量。

举一个非常简单的例子:

我的PythonScript.py:

print "foo_1: {}".format(foo_1)

有没有办法直接导入它们? 另外,如果可能的话,我不想更改 bash 脚本,因为它是一个在其他地方多次引用的公共文件。

如果您的.bash文件按照您的指示格式化 - 您可以通过imp模块将其直接作为 Python 模块imp

import imp
bash_module = imp.load_source("bash_module, "/path/to/myGlobalVariables.bash")
print bash_module.foo_1

您还可以使用 os.environ:

重击:

#!/bin/bash
# works without export as well
export testtest=one

蟒蛇:

#!/usr/bin/python
import os
os.environ['testtest']  # 'one'

我对 python陌生,所以我欢迎提供更多惯用方法的建议,但是下面的代码使用 bash 本身告诉我们通过首先在空环境( env -i bash )中调用 bash 来告诉我们设置了哪些值我们将哪些变量设置为基线,然后我再次调用它并告诉 bash 获取您的“变量”文件,然后告诉我们现在设置了哪些变量。 删除一些误报和明显的空白行后,我遍历“附加”输出,寻找不在基线中的变量。 新看到的变量被拆分(小心地)并放入bash字典中。 我已经离开(但注释掉了)我之前使用exec在 python 中本地设置变量的想法,但我遇到了引用/转义问题,所以我切换到使用 dict 。

如果对“变量”文件的确切调用(路径等)与我的不同,那么您需要更改该值的所有实例——在list.remove() subprocess.check_output()调用中,在list.remove()调用。

这是我使用的示例变量文件,只是为了演示一些可能发生的事情:

foo_1="var1"
foo_2="var2"
foo_3="var3"
if [[ -z $foo_3 ]]; then
    foo_4="test"
else
    foo_4="testing"
fi
foo_5="O'Neil"
foo_6='I love" quotes'
foo_7="embedded
newline"

...这是python脚本:

#!/usr/bin/env python

import subprocess

output = subprocess.check_output(['env', '-i', 'bash', '-c', 'set'])
baseline = output.split("\n")

output = subprocess.check_output(['env', '-i', 'bash', '-c', '. myGlobalVariables.bash; set'])
additional = output.split("\n")

# these get set when ". myGlobal..." runs and so are false positives
additional.remove("BASH_EXECUTION_STRING='. myGlobalVariables.bash; set'")
additional.remove('PIPESTATUS=([0]="0")')
additional.remove('_=myGlobalVariables.bash')
# I get an empty item at the end (blank line from subprocess?)
additional.remove('')

bash = {}
for assign in additional:
        if not assign in baseline:
                name, value = assign.split("=", 1)
                bash[name]=value
                #exec(name + '="' + value + '"')

print "New values:"
for key in bash:
  print "Key: ", key, " = ", bash[key]

另一种方法:

受到Marat回答的启发,我想出了这个两阶段的 hack。 从 python 程序开始,我们称之为“阶段 1”,它使用subprocess调用 bash 来获取变量文件,正如我上面的答案所做的那样,但它然后告诉 bash 导出所有变量,然后执行其余的您的 Python 程序,处于“第 2 阶段”。

第 1 阶段 python 程序:

#!/usr/bin/env python

import subprocess

status = subprocess.call(
  ['bash', '-c',
  '. myGlobalVariables.bash; export $(compgen -v); exec ./stage2.py'
  ]);

第 2 阶段 python 程序:

#!/usr/bin/env python
# anything you want! for example,
import os
for key in os.environ:
  print key, " = ", os.environ[key]

正如@theorifice 回答中所述,这里的技巧可能是这种格式化的文件可以被解释为 bash 和 python 代码。 但他的回答已经过时了。 不推荐使用imp模块以支持importlib

由于您的文件具有“.py”以外的扩展名,您可以使用以下方法:

from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("foobar", SourceFileLoader("foobar", "myGlobalVariables.bash"))
foobar = module_from_spec(spec)
spec.loader.exec_module(foobar)

我不完全理解这段代码是如何工作的(有这些 foobar 参数的地方),但是,它对我有用。 在这里找到

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM