2015-11-05 183 views
0

我試圖編寫一個用於構建某些軟件的python包裝器。我需要使用不同的配置自動創建數百次,這意味着我不能只是autogen.sh ; ./configure ; make ; make install。我使用的一些配置需要運行有條件地設置一些環境變量的腳本。我要的是能夠做這樣的事情:運行多個shell命令並等待結果的Python腳本

command = './autogen.sh' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = './script.sh ; ./configure <configure-flags>' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = 'make' 
ret = subprocess.call(command.split()) 
if ret != 0: 
    sys.exit(ret) 

command = 'make install' 
ret = subprocess.call(command.split()) 
if ret != 0): 
    sys.exit(ret) 

我遇到的問題是,在script.sh設置環境變量沒有得到保存configure。我在Sending multiple commands to a bash shell which must share an environment中看到了部分解決方案,但涉及將命令刷新到stdin並輪詢一個結果,當您有一個非常長的makefile時(我的大約需要10-20分鐘),它不會真正起作用,它也不會給出你是我需要知道的構建是否成功的返回值。

有沒有人知道更好的方法來做到這一點?

回答

0

這裏的基本問題是環境變量只能「向下」(從父到子)複製,從不「向上」(從子到父)。你的python腳本是父母。它運行一個shell命令,因此它是一個孩子; shell運行更多命令,這些命令是shell的子進程(因此也是Python進程的孫子)。

爲了使環境變量保持不變,您需要以某種方式向上導入它們。究竟是如何取決於你。一個常用的技術(在shell腳本和Python中使用)是讓導出器打印它想要設置的值,然後讓shell或Python進程讀取輸出並進行設置。 (我看這就是你鏈接到的確實後)

例如,子進程可能會打印:

CONFIG_PATH=/path/to/config/file 

(或export添加相同),然後外殼只會eval這個。這意味着很大的信任:如果孩子的過程打印rm -rf /例如?在執行之前,可以將規則(例如正則表達式匹配)應用於輸出,甚至可以手動(或自動)分析它,但在驗證步驟之後才執行結果。

另一種方法是將配置寫入文件,並讓父文件讀取該文件。這是幾乎相同的技術,但使用通信軟件倉庫的文件,而不是擺弄stdin和stdout。它還有幾個問題(命名文件,並知道何時讀取它)。

(有,當然,用Python編寫的許多構建和/或測​​試框架。我不會推薦任何一種特定的,因爲我沒有跟他們說太多的經驗。)

+0

我實際上不是所有的挑剔環境從一個'調用(被保存)'到另一個。我只需在每個'call()'中調用安裝腳本即可。 –

+0

「如果子進程打印'rm -rf /'」如果子進程直接執行'rm -rf /'怎麼辦? –

+0

@thatotherguy:的確如此。 :-)然而,我正考慮使用較窄的通信渠道來運行更多的大型系統,這些系統可以隔離(不同的UID,甚至可以在不同的虛擬機上運行)等子項。 – torek

1

如果你有一個腳本來設置你想要訪問的變量,你必須提供它(類似於其他語言所稱的「include」)。

而不是

command = './script.sh ; ./configure <configure-flags>' 
ret = subprocess.call(command.split()) 

你可以做

command = ["bash", "-c", "source script.sh; ./configure"] 
subprocess.call(command) 
相關問題