最近接到一個使用python寫一個解析yaml文件,並根據內容配置指定對應的shell來執行(比如bat、powershell、bash、csh、zsh等)命令的功能,於是考慮使用subprocess.Popen模塊來實現執行命令相關的功能,subprocess.Popen詳細的參數這里不細述,自己在測試執行python命令查看輸出顯示如下錯誤信息
>>> pipe=subprocess.Popen(['python','-c',"import os;print(os.environ.get('test'))"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,env={'test':'hello world'}) >>> print pipe.stdout.read() hello world Error processing line 5 of C:\Python27\lib\site-packages\pywin32.pth: Traceback (most recent call last): File "C:\Python27\lib\site.py", line 152, in addpackage exec line File "<string>", line 1, in <module> File "C:\Python27\lib\os.py", line 425, in __getitem__ return self.data[key.upper()] KeyError: 'PATH' Remainder of file ignored
這時仔細查看subprocess.Popen詳細env的參數說明
env參數:
如果env不是None,則子程序的環境變量由env的值來設置,而不是默認那樣繼承父進程的環境變量。注意,即使你只在env里定義了
某一個環境變量的值,也會阻止子程序得到其
他的父進程的環境變量(也就是說,如果env里只有1項,那么子進程的環境變量就只有1個了)
發現是設置env環境變量的值之后則子程序不再繼承父進程的環境變量了,這個時候打印子程序里面對應的環境變量可以發現只有env中指定的相關值了,咱們使用os.environ測試下
>>> pipe=subprocess.Popen(['python','-c',"import os;print os.environ"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,env={'test':'hello world'}) >>> print pipe.stdout.read() {'TEST': 'hello world'} Error processing line 5 of C:\Python27\lib\site-packages\pywin32.pth: Traceback (most recent call last): File "C:\Python27\lib\site.py", line 152, in addpackage exec line File "<string>", line 1, in <module> File "C:\Python27\lib\os.py", line 425, in __getitem__ return self.data[key.upper()] KeyError: 'PATH' Remainder of file ignored >>>
可以發現對應的環境變量中只剩下{'TEST': 'hello world'}了,這時候因為沒有繼承父進程中的環境變量所以PATH變量也就不存在了,所以這時候就會報錯,解決辦法是設置env變量的將PATH變量一起加上就可以了,如果不加上PATH執行一些非shell內建命令時會提示“不是內部或外部命令,也不是可運行的程序 或批處理文件”,這是因為PATH不存在相應的命令也就搜索不到了加上就可以了
>>> pipe=subprocess.Popen(['python','-c',"import os;print(os.environ.get('test'))"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT,env={'test':'hello world','PATH':os.environ.setdefault('PATH')}) >>> print pipe.stdout.read() hello world >>>