为什么我的python函数被跳过了?

时间:2015-02-05 18:41:59

标签: python popen

我有一个试图执行外部命令的小脚本。但由于某种原因,我完全跳过了执行命令的功能!似乎没有出现任何错误,它只是没有执行。我在里面有一些调试打印语句来验证函数是否已输入,但它们从不打印。我在它之外有一个打印声明来验证脚本没有死亡。那是什么给出了什么?

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" )

2 个答案:

答案 0 :(得分: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" )

答案 1 :(得分: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)

要丢弃孩子的stdout / stderr而不是保存它,请使用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