【问题标题】:Can python script know the return value of C++ main function in the Android environmentpython脚本能否知道Android环境下C++主函数的返回值
【发布时间】:2015-09-08 04:20:16
【问题描述】:

有几种调用 C++ 可执行程序的方法。例如,我们可以使用

 def run_exe_return_code(run_cmd):
        process=subprocess.Popen(run_cmd,stdout=subprocess.PIPE,shell=True)
        (output,err)=process.communicate()
        exit_code = process.wait()
        print output
        print err
        print exit_code
        return exit_code

处理 C++ 可执行程序:run_exe_return_code('abc')abc 由以下 C++ 代码创建:

int main()
{
      return 1;
}

在上面的代码中,程序的返回值是1,如果我们在Linux中运行这个Python脚本,我们总是可以看到Python脚本的返回值是1。但是,在Android环境下,似乎返回上述python脚本中的退出码为0,表示成功。有没有办法让Python脚本知道Android环境下main函数的返回值?

顺便说一句,在android环境中,我使用adb shell abc而不是abc来运行程序。

【问题讨论】:

  • 你能描述一个实际的例子吗?是什么让您认为 0 不是正确答案?
  • @ReutSharabani 测试起来很简单。在 main() 函数中,你只能返回 1。然后你只需运行 run_exe_return_code python 函数,exit_code 为 0。然后,如果你将 main() 函数中的返回值更改为 0,并运行一次 python 脚本再次,你会发现 exit_code 仍然是 0。
  • @feelfree 那么为什么不使用int main(){return 1;} 制作一个complete 示例呢?它将避免混淆,更重要的是,它可以立即编译。
  • @PadraicCunningham 有什么理由让他的代码不起作用?我使用了相同的功能并且它有效。它有什么缺点吗?
  • @ReutSharabani,通信已经阻塞等待进程终止,等待也会导致死锁docs.python.org/2/library/subprocess.html#subprocess.Popen.wait

标签: python c++


【解决方案1】:

对于您的 android 问题,您可以使用 fb-adb 哪个“传播程序退出状态而不是总是以状态 0 退出”(首选),或者使用这个 workaround(hackish...不是推荐用于生产):

def run_exe_return_code(run_cmd):
        process=subprocess.Popen(run_cmd + '; echo $?',stdout=subprocess.PIPE,shell=True)
        (output,err)=process.communicate()
        exit_code = process.wait()
        print output
        print err
        print exit_code
        return exit_code

注意最后一个进程的代码是echo-ed,所以从输出中获取它,而不是从adb的exit_code中获取。

$? 返回最后一个退出代码。所以打印它可以让你从 python 访问它。


关于你原来的问题:

我无法重现这个。这是一个简单的例子:

.c 文件的内容:

reut@reut-VirtualBox:~/pyh$ cat c.c 
int main() {
    return 1;
}

编译(默认为a.out...):

reut@reut-VirtualBox:~/pyh$ gcc c.c

.py 文件的内容:

reut@reut-VirtualBox:~/pyh$ cat tstc.py 
#!/usr/bin/env python

import subprocess

def run_exe_return_code(run_cmd):
    process=subprocess.Popen(run_cmd,stdout=subprocess.PIPE)
    (output,err)=process.communicate()
    exit_code = process.wait()
    print output
    print err
    print exit_code

run_exe_return_code('./a.out')

测试:

reut@reut-VirtualBox:~/pyh$ ./tstc.py 

None
1

exit_code1,正如预期的那样。

请注意,返回值始终是整数。您可能想要使用subprocess.check_output 获得的输出:

使用参数运行命令并将其输出作为字节字符串返回。

例子:

>>> subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'

注意:如果返回值为1,表示错误,则会引发CalledProcessError 异常(这通常是一件好事,因为您可以响应它)。

【讨论】:

  • check_output 如果退出状态不为零,则会引发 CalledProcessError,因此您必须捕获异常
  • 这是假设他正在寻找写给stdout的内容,但感谢您的评论。
  • 是的,但如果代码返回 1,您将看不到输出,程序将出错。你也不需要 shell=True
  • 很高兴shell=True 被删除了,这几乎不是一个好主意。此外,check_call 不应用作捕获错误代码的方法,但当返回代码非零时是一种例外情况。当存在一个平等对待所有返回值的替代方案时,看到try...catch 正常操作的语义(即期待异常)是令人困惑的。
【解决方案2】:

我想你可以试试 commands.getstatusoutput,像这样:

import commands

status, result = commands.getstatusoutput(run_cmd)

print result

【讨论】:

  • 谢谢,我重新编辑了这个问题,因为我发现这只是Android的一个问题。
【解决方案3】:

是的,你可以! 您提交的代码的简单版本是:

import subprocess
exit_code=subprocess.call('./a.out')`
print exit_code

使用 ./a.out 编译出的程序:

int main(){
    return 3;
}

测试:

python testRun.py
3

啊,请注意 shell=True 可能存在安全隐患。 https://docs.python.org/2/library/subprocess.html

def run_exe_return_code(run_cmd):
    process=subprocess.Popen(run_cmd,stdout=subprocess.PIPE,shell=True)

【讨论】:

【解决方案4】:

看到这个答案:https://stackoverflow.com/a/5631819/902846。将其调整为您的示例,它看起来像这样:

def run_exe_return_code(run_cmd):
    process = subprocess.Popen(run_cmd, stdout=subprocess.PIPE, shell=True)
    (output, err) = process.communicate()
    process.wait()
    print output
    print err
    print process.returncode
    return process.returncode

简短的总结是,您可以酌情使用Popen.waitPopen.pollPopen.communicate来更新返回码,然后再用Popen.returncode检查返回码。

另请参阅 Popen 的 Python 文档:https://docs.python.org/2/library/subprocess.html

【讨论】:

  • 谢谢,我重新编辑了这个问题,因为我发现这只是Android的问题。
【解决方案5】:
def run_exe_android_return_code(run_cmd):
     #adb shell '{your command here} > /dev/null 2>&1; echo $?'
     process=subprocess.Popen(run_cmd,stdout=subprocess.PIPE,shell=True)
     (output,err)=process.communicate()
     pos1   = output.rfind('\n')
     output = output[:pos1-1]
     pos2   = output.rfind('\n')
     output = output[pos2+1:]
     print output
     return output

这是用于检查在 Android 上运行可执行文件的返回值的 Python 脚本。

def run_android_executable(full_path,executable):
    executable = full_path+'/'+executable
    run_cmd = 'adb shell \'LD_LIBRARY_PATH='+full_path+':$LD_LIBRARY_PATH '+executable+'; echo $?\''
    print run_cmd
    error_code=run_exe_android_return_code(run_cmd)
    print 'the error code is'
    print error_code
    if(error_code=='1'):
        print 'the executable returns error'
    else:
        print 'the exectuable runs smoothly'

这是用于运行可执行文件的脚本。这与 Reut Sharabani 的回答略有不同,并且有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多