2015-02-05 26 views
2

我有一個試圖執行外部命令的小腳本。但由於某種原因,我執行該命令的功能正在被完全跳過!似乎沒有錯誤提出,它只是不執行。我在裏面有一些調試打印語句來驗證函數是否進入,但他們從不打印。我在它外面有一個打印語句來驗證腳本沒有死掉。那麼是什麼給了?爲什麼我的Python函數被跳過?

from xml.etree import ElementTree as et 
import subprocess 

pomFileLocation = "pom.xml" 
uiAutomationCommand = "mvn clean install" 
revertPomFileCommand = "git checkout pom.xml" 
profileToSetToDefault = "smoketest" 

def modifyxml(datafile, value): 
    print("modifying " + datafile) 
    tree = et.parse(datafile) 
    rootNodes = tree.getroot() 
    for node in rootNodes: 
     if "profiles" in node.tag: 
      for profile in node.iter(): 
       foundIt = False 
       for param in profile.iter(): 
        if "id" in param.tag and profileToSetToDefault in param.text: 
         foundIt = True 
         break 
       if foundIt == True: 
        for param in profile.iter(): 
         if "activation" in param.tag: 
          for child in param.iter(): 
           if "activeByDefault" in child.tag: 
            child.text = value 
            tree.write(datafile) 
            return 

def runExternalCommand(comm): 
    print("running command " + comm) 
    p = subprocess.Popen(comm, bufsize=-1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] 
    print(str(p)) 
    while(True): 
     print("still running") 
     retcode = p.poll() 
     line = p.stdout.readline() 
     yield line 
     if(retcode is not None): 
      print("Exiting") 
      break 
    return 

if __name__ == '__main__': 
    modifyxml(pomFileLocation, "true") 
    #runExternalCommand(uiAutomationCommand) 
    runExternalCommand(revertPomFileCommand) 
    print("finished") 
+0

你在哪裏得到'runExternalCommand()'定義?它被打破。請留下您的評論,以便其他人不會使用破損的代碼。 [我的答案提供了一些替代方法](http://stackoverflow.com/a/28352727/4279) – jfs 2015-02-05 19:49:47

回答

2

runExternalCommand使用yield,所以如果你希望它一路執行到底,你應該稱呼它for something in runExternalCommand(revertPomFileCommand):。或者直接刪除yield這一行,因爲你似乎並不需要它。

def runExternalCommand(comm): 
    print("running command " + comm) 
    p = subprocess.Popen(comm, bufsize=-1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] 
    print(str(p)) 
    while(True): 
     print("still running") 
     retcode = p.poll() 
     line = p.stdout.readline() 
     yield line 
     if(retcode is not None): 
      print("Exiting") 
      break 
    return 

if __name__ == '__main__': 
    modifyxml(pomFileLocation, "true") 
    #runExternalCommand(uiAutomationCommand) 
    for line in runExternalCommand(revertPomFileCommand): 
     pass 
    print("finished") 

或者

def runExternalCommand(comm): 
    print("running command " + comm) 
    p = subprocess.Popen(comm, bufsize=-1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] 
    print(str(p)) 
    while(True): 
     print("still running") 
     retcode = p.poll() 
     line = p.stdout.readline() 
     if(retcode is not None): 
      print("Exiting") 
      break 
    return 

if __name__ == '__main__': 
    modifyxml(pomFileLocation, "true") 
    #runExternalCommand(uiAutomationCommand) 
    runExternalCommand(revertPomFileCommand) 
    print("finished") 
+0

啊。這就是我從互聯網上盲目複製和粘貼的結果。我不知道收益會做到這一點。我刪除它,現在它可以工作。謝謝! – user2623609 2015-02-05 18:50:24

+0

爲了澄清,這不是函數運行到yield-statement。相反,直到它迭代完成纔會運行。 yield-statement之前的位也不會運行。 – 2015-02-05 18:50:25

+0

如果您故意使用破損的代碼,請添加所有CAPSLOCK免責聲明。 – jfs 2015-02-05 19:54:34

1

由於@Kevin said,主要(但不是唯一的)問題是runExternalCommand是發電機。要消耗它,你可以運行:print(list(runExternalCommand(revertPomFileCommand)))

雖然功能runExternalCommand()被打破:沒有一點叫p.stdout.readline().communicate()回報(子進程結束後等待並立即返回整個輸出)。

目前尚不清楚你想要得到例如,運行git命令和存儲其在一個可變輸出什麼結果,你可以使用subprocess.check_output()

from subprocess import check_output, STDOUT 

output = check_output("git checkout pom.xml".split(), 
         stderr=STDOUT, universal_newlines=True) 

要放棄孩子的標準輸出/標準錯誤,而不是保存,使用subprocess.check_call()

from subprocess import check_call, DEVNULL, STDOUT 

check_call("git checkout pom.xml".split(), 
      stdout=DEVNULL, stderr=STDOUT) 

對於代碼示例,以讀取輸出,同時子進程仍在運行,見Constantly print Subprocess output while process is running