从python中的子进程返回一个变量值

时间:2015-06-22 14:39:57

标签: python python-2.7 subprocess

我有一个代码工作流,从主脚本(级别0)我通过subprocess调用另一个脚本。此subprocess script(级别1)又将另一个脚本调用为subprocess。现在从这个2级子进程脚本我想要将变量的值返回到主脚本(级别0)。我试过Popen.communicate(),但我无法返回值。我目前的代码如下:

main_script.py

def func():

    para = ['a','b']
    result = subprocess.Popen([sys.executable,"first_subprocess.py"]+para,stdout=subprocess.PIPE)
    result.wait()

    return_code = result.returncode
    out, err = sub_result.communicate()


    if return_code == 1:
        return return_code

    else:
        if out is not None:
            print 'return value: ', out


if __name__ == '__main__':

    func()

从上面的脚本称为first_subprocess.py,其中包含:

def some_func():

    # some other code and multiple print statements

    para = ['a','b']
    result = subprocess.Popen([sys.executable,"second_subprocess.py"]+para,stdout=subprocess.PIPE)

    result.wait()
    out, err = result.communicate()
    return_code = sub_result.returncode
    if return_code == 0:
        return out


if __name__ == '__main__':

    some_func()

second_subprocess.py返回如下值:

def test():
    # some other code and multiple print statements
    val = 'time'
    print 'returning value'
    return val   

if __name__ == '__main__':    

    test()

当我尝试上面的代码时,我将代码中的所有print语句作为输出而不是返回值。即使尝试print子进程中的变量值而不是返回它也不会达到目的,因为有多个print语句。

在这种情况下如何返回变量值?

更新版本:

在@Anthons建议之后,我修改了我的first_subprocess.py脚本和main_script.py,如下所示:

first_subprocess.py:

def some_func():

   try:
    key = None
    if not (key is None):

       para = ['a','b']
       result = subprocess.Popen([sys.executable,"second_subprocess.py"]+para,stdout=subprocess.PIPE)

       sub_result.wait()
       out, err = sub_result.communicate()
       return_code = sub_result.returncode
       if return_code == 0:
       for line in out.splitlines():
           if not line.startswith('>>>'):
              continue
           print line
   else:
     sys.exit(0)
 except:
   return 1

Main_script.py:

if out is not None:
   for line in out.splitlines():
       if not line.startswith('>>>'):
          continue
      value = line.split(':',1)[1].lstrip()

print 'return value:',value`

当我在上面执行时,我在UnboundLocalError: local variable 'value' referenced before assignment命令获得print value。看来如果我不执行第1级脚本中的代码并执行sys.exit(),那么主脚本中的out既不是空的也不是空的,但它有一些未定义的值,因此value变量没有初始化并抛出错误

1 个答案:

答案 0 :(得分:1)

如果您只想返回一个整数值,可以使用退出值。这与从some_func()返回的情况不同,您必须执行sys.exit(integer_val)

如果要返回类似time的字符串,则应打印该字符串(或写入sys.stdout),然后在调用进程(级别1)中解析子进程的输出并将其打印到它自己的stdout为0级才能看到它。

在你的情况下,二级应该做类似的事情:

def test():
    # some other code and multiple print statements
    val = 'time'
    print 'returning value:', val

if __name__ == '__main__':    
    test()

在第1级你会这样做:

def some_func():

    # some other code and multiple print statements

    para = ['a','b']
    result = subprocess.Popen([sys.executable,"second_subprocess.py"]+para,stdout=subprocess.PIPE)

    result.wait()
    out, err = result.communicate()
    return_code = sub_result.returncode
    if return_code == 0:
        print out

if __name__ == '__main__':
    some_func()

使用main_script.py可以从调用1级脚本中读取内容。

我通常使用subprocess.check_output()来传递这些信息。如果被调用进程具有非零退出状态(即出错时),则抛出异常。我还建议,如果子进程写入的信息多于变量,则可以通过在行的开头返回唯一的东西来使输出行易于解析(因此您仍然可以使用print语句来调试单个脚本从输出中获取正确的值):

等级2:

def test():
    # some other code and multiple print statements
    print 'debug: Still going strong'
    val = 'time'
    print '>>>> returning value:', val

if __name__ == '__main__':    
    test()

等级1:

...
out, err = result.communicate()
for line in out.splitlines():
    if not line.startswith('>>>>'):
        continue
    print line
...

等级0:

...
out, err = result.communicate()
for line in out.splitlines():
    if not line.startswith('>>>>'):
        continue
    try:
        value = line.split(':', 1)[1]
    except IndexError:
        print 'wrong input line', repr(line)
    print 'return value: ', value
...

以下文件一起使用。将它们保存在指定的名称下

<强> lvl2.py

# lvl2
import sys

def test():
    # some other code and multiple print statements
    print >> sys.stderr, 'argv', sys.argv[1:]
    print 'debug: Still going strong'
    val = 'time'
    print '>>>> returning value:', val
    return 0

if __name__ == '__main__':
    sys.exit(test())

<强> lvl1.py

# lvl1.py
import sys
import subprocess

def some_func():
    para = ['a','b']
    sub_result = subprocess.Popen(
        [sys.executable, "lvl2.py" ] + para,
        stdout=subprocess.PIPE)
    sub_result.wait()
    out, err = sub_result.communicate()
    return_code = sub_result.returncode
    if return_code == 0:
        for line in out.splitlines():
            if not line.startswith('>>>'):
                continue
            print line
    else:
        print >> sys.stderr, 'level 2 exited with' + return_code
    sys.exit(0)

if __name__ == '__main__':
    sys.exit(some_func())

<强> lvl0.py

# lvl0
import subprocess
import sys

def func():
    para = ['a','b']
    result = subprocess.Popen(
        [sys.executable, "lvl1.py"] + para,
        stdout=subprocess.PIPE)
    result.wait()
    return_code = result.returncode
    out, err = result.communicate()

    value = None
    if return_code == 0:
        for line in out.splitlines():
            if not line.startswith('>>>'):
                continue
            value = line.split(':',1)[1].lstrip()
            print
    else:
        print 'non-zero exit', return_code
    print 'return value:', value

if __name__ == '__main__':
    func()

然后运行python lvl0.py以检查输出是否为

argv ['a', 'b']

return value: time

现在将这些内容放在您的修订控制系统下,并开始一次更改几行,每次都运行python lvl0.py以检查您可能已经损坏的内容。提交每个修订版本,以便您可以回滚到最后一个“已知良好”状态并慢慢引入其余代码。