如何从C++函数中保存输出,到Python变量

2024-05-21 09:02:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经在C++中使用Boosi.Python脚本中有工作函数。p>

此函数正在向我打印一些数据(字符串) 要调用此函数,我使用以下代码:

import cpp as cpp_fun #importing from c++ already compiled with boost (no exe)
file = path_to_file #doesn't matter which file
cpp_fun.strings(file)#gives me output
output:
"this is test string, one line of many.." 

我甚至不需要使用print(cpp_fun.strings())来打印输出,所以问题是, 我不能将它添加到变量中,然后打印这个变量,因为当我运行python时,这个函数一直在打印输出

我想将输出从cpp_fun.strings()保存到变量 但是当我做的时候:

strings = cpp_fun.strings()

它再次给我输出

我试图创建方法(def())并将此函数放入其中,但结果还是一样的, 我还尝试捕捉输出:

old_stdout = sys.stdout
new_stdout = StringIO()
sys.stdout = new_stdout
print(cp_fun.strings())
output = new_stdout.getvalue()
sys.stdout = old_stdout

但是,如果没有成功,上面的这个捕获对普通打印有效,但对这一个无效。 我还尝试添加了var=subprocess.check_output([cpp_fun])-不起作用 也许你有办法把它保存到变量中


Tags: 数据函数脚本newoutputstdoutsyscpp
1条回答
网友
1楼 · 发布于 2024-05-21 09:02:22

cpp扩展模块替换为一个普通的Python扩展模块,它只打印作为参数接收的文件的每一行
下面是捕获其输出的示例

cpp.py

def strings(file_name):
    with open(file_name) as f:
        for line in f:
            print(line.rstrip())

code00.py

#!/usr/bin/env python

import sys
import io
import traceback

import cpp as cpp_fun


def capture_function_output(func, *func_args):
    tmp_buf_out = io.StringIO()
    tmp_buf_err = io.StringIO()
    _sys_stdout = sys.stdout
    sys.stdout = tmp_buf_out
    _sys_stderr = sys.stderr
    sys.stderr = tmp_buf_err
    try:
        func_ret = func(*func_args)
    except:
        func_ret = None
        traceback.print_exc()
    tmp_buf_out.flush()
    tmp_buf_err.flush()
    sys.stdout = _sys_stdout
    sys.stderr = _sys_stderr
    tmp_buf_out.seek(0)
    func_stdout = tmp_buf_out.read()
    tmp_buf_err.seek(0)
    func_stderr = tmp_buf_err.read()
    return func_ret, func_stdout, func_stderr


def test_capture_cpp_fun_output(file_name):
    retcode, sout, serr = capture_function_output(cpp_fun.strings, file_name)  # Store function return code, stdout and stderr contents into 3 variables
    print("Function ({0:s}) returned: {1:}".format(cpp_fun.strings.__name__, retcode))
    print("Function printed to stdout: \n{0:s}".format(sout))
    print(" - Done")
    print("Function printed to stderr: \n{0:s}".format(serr))
    print(" - Done")


def main(*argv):
    for file_name in [
        "dummy.txt",
        "dummy.txt0",  # Doesn't exist!
    ]:
        print("\nTesting file: {0:s}:".format(file_name))
        test_capture_cpp_fun_output(file_name)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

输出

e:\Work\Dev\StackOverflow\q060851454>sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> type dummy.txt
dummy line 0
next line
0123456789

[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32


Testing file: dummy.txt:
Function (strings) returned: None
Function printed to stdout:
dummy line 0
next line
0123456789

 - Done
Function printed to stderr:

 - Done

Testing file: dummy.txt0:
Function (strings) returned: None
Function printed to stdout:

 - Done
Function printed to stderr:
Traceback (most recent call last):
  File "code00.py", line 18, in capture_function_output
    func_ret = func(*func_args)
  File "e:\Work\Dev\StackOverflow\q060851454\cpp.py", line 2, in strings
    with open(file_name) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'dummy.txt0'

 - Done

Done.



更新#0

将代码更改为同时捕获函数的stderr



更新#1

添加基于[Python 3.Docs]: subprocess - Subprocess management的变量(这在我这边也适用)。这需要一个额外的脚本(cpp\u wrapper.py,它依赖于上面的cpp.py

cpp_wrapper.py:

import sys

import cpp as cpp_fun


if __name__ == "__main__":
    if (len(sys.argv) < 2):
        raise RuntimeError("Missing argument")
    file_name = sys.argv[1]
    try:
        cpp_fun.strings(file_name)
    except:
        raise
else:
    raise RuntimeError("This module should be executed directly")

code01.py

#!/usr/bin/env python

import sys
import subprocess


def capture_cpp_fun_output(file_name):
    cmd = (sys.executable, "cpp_wrapper.py", file_name)
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    return p.returncode, out.decode(), err.decode()


def main(*argv):
    for file_name in [
        "dummy.txt",
        "dummy.txt0",  # Doesn't exist!
    ]:
        print("\nTesting file: {0:s}:".format(file_name))
        retcode, sout, serr = capture_cpp_fun_output(file_name)  # Store function return code, stdout and stderr contents into 3 variables
        print("Function returned: {0:}".format(retcode))
        print("Function printed to stdout: \n{0:s}".format(sout))
        print(" - Done")
        print("Function printed to stderr: \n{0:s}".format(serr))
        print(" - Done")



if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

输出

[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code01.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32


Testing file: dummy.txt:
Function returned: 0
Function printed to stdout:
dummy line 0
next line
0123456789

 - Done
Function printed to stderr:

 - Done

Testing file: dummy.txt0:
Function returned: 1
Function printed to stdout:

 - Done
Function printed to stderr:
Traceback (most recent call last):
  File "cpp_wrapper.py", line 11, in <module>
    cpp_fun.strings(file_name)
  File "e:\Work\Dev\StackOverflow\q060851454\cpp.py", line 2, in strings
    with open(file_name) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'dummy.txt0'

 - Done

Done.

相关问题 更多 >