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

标签 python python-2.7 subprocess

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

ma​​in_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`

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

最佳答案

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

如果你想返回像 time 这样的字符串,你应该打印它(或写入 sys.stdout ),然后在调用过程中(级别 1)解析子进程的输出并将其打印到自己的标准输出以供 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() 来传递这些信息。如果被调用的进程具有非零退出状态(即出错),则会引发异常。我还可以建议,如果子进程写入的信息不仅仅是变量,您可以通过在行的开头返回一些独特的内容来使输出行易于解析(这样您仍然可以使用打印语句来调试各个脚本 从输出中获取正确的值):

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

一级:

...
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 以检查您可能损坏的内容。提交每个修订版,这样您就可以回滚到上一个“已知良好”状态,然后慢慢引入其余代码。

关于python - 从python中的子进程返回一个变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30982820/

相关文章:

python - 'second_file' 没有属性 'hello' -- Discord Python Bot

python - 从 dict 以列表作为值创建 DataFrame

Python - 无效的 JSON 格式 - 如何解析

python - 使用 "genfromtxt"提取列

python - 将 SIGINT 信号委托(delegate)给子进程,然后清理并终止父进程

python - 如何通过 python 将命令绕过另一个终端内的终端?

python - 如何在python2中捕获在python3中运行的命令的输出?

python - 如何找到列表中第二大的数字?

python - 在Python迭代器中保持相同的值

javascript - 高级 API : calling into Odoo models HowTo