1. 程式人生 > WINDOWS開發 >解決subprocess.Popen在windows下執行命令報的KeyError: 'PATH'問題

解決subprocess.Popen在windows下執行命令報的KeyError: 'PATH'問題

最近接到一個使用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"],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",in addpackage
      exec line
    File "<string>",in <module>
    File "C:\Python27\lib\os.py",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,env={test:hello world,PATH:os.environ.setdefault(PATH)})
>>> print pipe.stdout.read()
hello world
>>>