从python脚本导入bash变量

时间:2016-11-29 16:23:05

标签: python shell import

我已经看到很多从bash脚本中运行python脚本并将变量作为参数传递或使用export来提供子shell访问的例子,我试图在这里做相反的事情。

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

  

myGlobalVariables.bash:

<ol>
  <li class="action-item">item 1</li>
  <li>item 2</li>
  <li>item 3</li>
  <li class="action-item">item 4</li>
  <li class="action-item">item 5</li>
  <li>item 6</li>
</ol>

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

一个非常简单的例子:

  

myPythonScript.py:

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

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

4 个答案:

答案 0 :(得分:1)

如果.bash文件的格式符合您的指示 - 您可以直接通过imp模块将其作为Python模块导入。

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

答案 1 :(得分:1)

您也可以使用os.environ:

击:

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

的Python:

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

答案 2 :(得分:0)

非常是python的新手,所以我欢迎更多惯用方法的建议,但下面的代码使用bash本身告诉我们通过首先调用bash来设置哪些值空环境(env -i bash)告诉我们哪些变量被设置为基线,然后我再次调用它并告诉bash来源&#34;变量&#34;文件,然后告诉我们现在设置了什么变量。在删除了一些误报和一条明显空白的行之后,我循环了另外一些&#34;输出,查找不在基线中的变量。新见变量被分割(仔细)并放入bash字典中。我已离开这里(但已注释掉)我之前使用exec在python中本地设置变量的想法,但我遇到了引用/转义问题,所以我转而使用dict。 / p>

如果确切的呼叫(路径等)到你的&#34;变量&#34;文件与我的不同,那么您需要更改该值的所有实例 - 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答案的启发,我想出了这个两阶段的黑客攻击。从python程序开始,让我们调用它&#34;阶段1&#34;,使用subprocess来调用bash来获取变量文件,正如我上面的回答所做的那样,但它然后告诉bash导出所有变量,然后执行你的python程序的其余部分,这是在&#34;阶段2&#34;。

第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]

答案 3 :(得分:0)

正如@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 参数的地方),但是,它对我有用。找到它 here