【问题标题】:Import bash variables from a python script从 python 脚本导入 bash 变量
【发布时间】:2016-11-29 16:23:05
【问题描述】:

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

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

myGlobalVariables.bash:

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

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

举个很简单的例子:

myPythonScript.py:

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

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

【问题讨论】:

  • 你的意思是你想从python解析bash文件?不会很容易。除了变量声明之外,您的脚本是否包含命令?
  • 有,但不多。试图避免解析,但如果这是唯一的选择,我绝对可以做到。
  • 你想引用的变量是所有的简单赋值吗?即var_name=var_val - 这样就没有shell扩展、命令替换等。

标签: python shell import


【解决方案1】:

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

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

【讨论】:

  • " imp.load_source(name, pathname[, file]) 加载并初始化实现为 Python 源文件的模块并返回其模块对象。"。没有提到 bash...
  • 根据 OP 对myGlobalVariables.bash 的描述 - 它可以被解释为 Python 文件。
  • 不错的技巧。可以工作... export 你就是历史 :)
  • 嗯,所以我尝试了这个并得到:SyntaxError:EOL,同时扫描字符串文字我认为这与格式错误有关。格式并不像我在示例中指出的那么简单,有几行没有遵循这一点。
  • 在这种情况下,您只需要解析内容。假设所有变量分配都很简单,您可能只需要使用正则表达式。
【解决方案2】:

你也可以使用 os.environ:

重击:

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

Python:

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

【讨论】:

  • 在这种情况下,您需要以某种方式从 Python 执行 .bash 文件 - 或者在 Python 代码运行之前执行它。
  • 在 python 中执行将不起作用。和之前:OP似乎说这很容易。确实如此。
  • @theorifice 我认为这个问题意味着在设置这些变量后从 bash 文件中调用 python 脚本
【解决方案3】:

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

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

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

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 程序开始,我们称之为“stage 1”,它使用subprocess 调用 bash 来获取变量文件,就像我上面的答案一样,但是它告诉 bash 导出所有变量,然后执行你的python程序的其余部分,处于“阶段2”。

第一阶段python程序:

#!/usr/bin/env python

import subprocess

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

第二阶段python程序:

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

【讨论】:

    【解决方案4】:

    正如@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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多