簡體   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