2016-11-29 115 views
1

我已經看到很多從bash腳本內部運行python腳本的例子,並且通過變量作爲參數傳遞或者使用export來給子shell訪問,我試圖在這裏做相反的事情雖然。從python腳本導入bash變量

我運行一個python腳本,並有一個單獨的文件,讓我們把它叫做myGlobalVariables.bash

myGlobalVariables.bash:

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

我的Python腳本需要使用這些變量。

對於一個非常簡單的例子:

myPythonScript.py:

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

有沒有一種方法我可以直接導入他們呢?另外,如果可能的話,我不想修改bash腳本,因爲它是其他地方多次引用的常用文件。

+0

你的意思是要分析從蟒蛇bash的文件嗎?並不容易。您的腳本是否包含變量聲明之外的命令? –

+0

它確實,但不是很多。試圖避免解析,但如果這是唯一的選擇,我肯定可以做到。 – Bagelstein

+0

你想引用所有簡單賦值的變量嗎?即'VAR_NAME = var_val' - 使得沒有殼擴展,命令替換等 – theorifice

回答

1

如果您的.bash文件按照您的指示格式化 - 您可能只需通過imp模塊直接將其作爲Python模塊導入。

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

「imp.load_source(名稱,路徑名[,文件]) 加載和初始化爲Python源文件中實現的模塊並返回它的模塊目的。」。慶典中沒有提到... –

+0

據'myGlobalVariables.bash'的OP的描述 - 它可以被解釋爲Python文件。 – theorifice

+0

漂亮的黑客。可以只是工作...一個'出口',你的歷史:) –

1

您還可以使用os.environ:

擊:

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

的Python:

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

在這種情況下,你需要以某種方式執行從Python中'.bash'文件雖然 - 或Python代碼運行之前執行它。在python中執行的 – theorifice

+0

將不起作用。和之前:OP似乎說這很容易。它是。 –

+0

@theorifice我覺得這個問題意味着Python腳本從bash的文件調用之後這些變量設定 – Marat

0

新的Python,所以我歡迎建議更習慣的方法來做到這一點,但下面的代碼使用bash它小精靈告訴我們哪些值是通過首先用空白環境調用bash來設置的(env -i bash),告訴我們什麼變量被設置爲基線,然後我再次調用並告訴bash來源您的「變量」文件,然後然後告訴我們現在設置了哪些變量。在刪除了一些假陽性和一條明顯空白的行後,我通過「額外」輸出循環查找不在基線中的變量。新的變量會被仔細分解並放入bash字典中。我已經離開這裏(但註釋掉了)我以前使用exec來設置python本地變量的想法,但是我遇到了引用/轉義問題,所以我轉而使用字典。

如果您的「變量」文件的確切呼叫(路徑等)與我的不同,那麼您需要更改該值的所有實例 - 在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程序,姑且稱之爲「階段1」,即用subprocess調用的bash到源變量文件,如我上面的回答呢,但隨後告訴Bash導出所有的變量,然後exec的其餘你的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]