2017-07-27 166 views
0

爲什麼我的Python解釋器的os.system('command')與終端的命令沒有相同的輸出?os.system與命令行有什麼不同?

問連忙解釋道:

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

os.system('echo $CONFPATH') 

0 

這是爲什麼?

詳細信息: 我想讓我的環境$ CONFPATH。我使用python3.5和ubuntu16.04.2。

我可以從命令行執行此操作:

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

這就是我想要的答案。

執行它作爲命令行Python的命令也適用:

python3 -c 'import os; print(os.environ["CONFPATH"])' 
/home/claramart/Datamart/Parameter 

的事情是,我想從我的Python解釋器執行此,而不是命令行。 從我的Python解釋器執行它不工作(我使用Pyzo4.4.1):

print(os.environ["CONFPATH"]) 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/usr/lib/python3.5/os.py", line 725, in __getitem__ 
    raise KeyError(key) from None 
KeyError: 'CONFPATH' 

我想這是嚴格從我的解釋,而不是來自Python本身作爲蟒蛇執行命令行工作。此外,我可以從我的python解釋器中獲得$ PYTHONPATH,所以我想它根本不檢測所有的環境變量。

爲了避免這一點,從命令行執行它的工作,我想這樣做,因爲從我的Python解釋器的命令行執行,但沒有我的2所命令行執行的工作,我希望的方式來:

os.system('echo $CONFPATH') 

0 

和:

os.system("""python3 -c 'import os; print(os.environ["CONFPATH"]'""") 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "/usr/lib/python3.5/os.py", line 725, in __getitem__ 
    raise KeyError(key) from None 
KeyError: 'CONFPATH' 
256 

再次在這兩種情況下,它的工作爲$ PYTHONPATH,所以我想它必須在某個時候通過我的翻譯,因爲我的問題是特定於變量$ CONFPATH。

爲什麼我的Python解釋器的os.system('command')與終端的命令沒有相同的輸出?

+0

在任何默認shell中運行該命令,然後您將獲得環境。所以:'os.system(「」「/ usr/bin/bash -c python3 -c'import os; print(os.environ [」CONFPATH「]'」「」)' - 可能沒有引用那個對或得到正確的路徑bash,但希望你能得到想法 – barny

+0

我明白了,但是我之前沒有用過這個和'os.system(「」「/ bin/bash -c python3 -c'import os; print(os .environ [「CONFPATH」]'「」「)'開始一個dos似乎沒有結束的進程,就像它被卡住了一樣。也許我做錯了嗎? – Ashargin

+0

」執行它從我的python解釋器不起作用Pyzo4.4.1)「我認爲Pyzo解釋器運行在不同的環境中,具有不同的環境變量,它是否在標準解釋器中工作? – Goyo

回答

2

我認爲你期待有一個環境。事實是,每個進程都有自己的環境,通常從其父進程繼承。不幸的是,我們在片段中沒有看到足夠的信息來告訴您如何傳遞這個特定的值,但我們可以通過它們看看他們實際上說了些什麼。

echo $CONFPATH 
/home/claramart/Datamart/Parameter 

這表明表明shell可能擴展參數$CONFPATH shell命令echo。但是,它並不顯示它是來自shell還是環境變量。不過,後面的代碼片段確實表明你確實有一個設置它的環境。

os.system('echo $CONFPATH') 

0 

這裏是一個Python函數調用,反過來調用C庫函數,這將導致一個新的外殼將被啓動,並解釋給定的命令。值得注意的是,這與你所運行的不一樣。它是一個新的/ bin/sh進程,它從進行調用的Python解釋器繼承了環境。我們看到這個shell命令成功(退出值0),並將CONFPATH擴展爲空,表明它在此處爲空或未設置Python解釋器的環境。

python3 -c 'import os; print(os.environ["CONFPATH"])' 
/home/claramart/Datamart/Parameter 

下面是一個啓動Python解釋器的shell命令的示例,該命令使用命令行打印環境變量。它成功了,因爲變量是從運行命令的shell中繼承的。

os.system("""python3 -c 'import os; print(os.environ["CONFPATH"]'""") 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "/usr/lib/python3.5/os.py", line 725, in __getitem__ 
    raise KeyError(key) from None 
KeyError: 'CONFPATH' 
256 

這裏一個被包裹在另一個;從Python解釋器開始,shell開始運行一個命令,該命令啓動另一個應該打印CONFPATH環境變量的Python解釋器。但是,這個內部Python代碼失敗,因爲在其環境中找不到CONFPATH而引發KeyError異常。這與shell僅僅顯示一個空值的行爲形成鮮明對比。由於沒有捕獲到異常,因此打印了一個回溯,Python shell返回了一個錯誤代碼,依次由子shell返回,最後由我們的外部Python解釋器打印爲256.

您已經顯示了兩個不同的命令環境:一個設置了CONFPATH的shell,以及一個其中沒有的Python解釋器。 pstree,ps fps -H可能會幫助您可視化過程樹,從而可以看到環境從何處繼承。請注意,環境是從父進程複製的;改變它在父母只會影響新的孩子,而不是現有的。

在Linux中,也可以在/ proc文件系統中找到環境。例如,tr \\0 \\n < /proc/$$/environ將打印從其運行的shell的環境(shell將$$擴展爲其自己的進程ID)。

當你從不同的環境中運行時,這種區別變得更加重要;例如,通過您的.profile.bashrc文件設置的任何內容都不會影響從cron運行的命令,並且與系統啓動腳本類似。大多數程序會保留原有環境,但有些程序會生成特定的例外,例如setuid程序忽略LD_LIBRARY_PATH,或者suenv重寫環境。

+0

令人驚歎的答案。 – Ashargin

1

嘗試出口 shell變量從父殼,即其中開始的Python殼:

 
$ CONFPATH=/home/claramart/Datamart/Parameter 
$ echo $CONFPATH 
/home/claramart/Datamart/Parameter 
$ env | grep CONFPATH 
$ python3 -c 'import os; print(os.environ["CONFPATH"])' 
Traceback (most recent call last): 
    File "", line 1, in 
    File "/usr/lib64/python3.5/os.py", line 725, in __getitem__ 
    raise KeyError(key) from None 
KeyError: 'CONFPATH' 
$ python3 -c 'import os; print(os.system("echo $CONFPATH"))' 

0 

# Try the same after exporting the variable 
$ export CONFPATH 
$ env | grep CONFPATH 
CONFPATH=/home/claramart/Datamart/Parameter 
$ python3 -c 'import os; print(os.environ["CONFPATH"])' 
/home/claramart/Datamart/Parameter 
$ python3 -c 'import os; print(os.system("echo $CONFPATH"))' 
/home/claramart/Datamart/Parameter 
0 

殼牌變量不是默認出口所以,上面的export命令之前,CONFPATH是實際上並沒有被父進程導出(你的終端的shell)。如上所示,您的Python進程在其環境中根本不應該定義CONFPATH

說了這麼多,我很驚訝地看到,查找os.environ中的環境變量顯然適用於您,而os.system()沒有。根據環境變量的可用性,兩者都應該工作,或兩者都不應該工作。也許這是使用Pyzo或你(或Pyzo)調用解釋器的方式的怪癖。

相關問題