Reputation:
I already have working function in my python script from C++ using boost.
This function is printing me some data (string) To call this function I am using this code:
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.."
I dont even need to use print(cpp_fun.strings())
to print output, so problem is,
that I cant add it to variable, and then print this variable, because this function is printing output all the time when I run python.
I want to save output from cpp_fun.strings()
to variable
but when I am doing :
strings = cpp_fun.strings()
It gives me output again...
I've tried to create method (def()
) and put this function inside , but with the same result after all,
also i have tried to catch output:
old_stdout = sys.stdout
new_stdout = StringIO()
sys.stdout = new_stdout
print(cp_fun.strings())
output = new_stdout.getvalue()
sys.stdout = old_stdout
But without success, this catch above is working for normal print but not for this one.
I've tried also add var=subprocess.check_output([cpp_fun])
-not working
Maybe you have any ideas how to save it to variable?
Upvotes: 1
Views: 1237
Reputation: 41127
Replaced your cpp extension module by a plain Python one, which simply prints every line of the file that it receives as an argument.
Below it's an example of capturing its output.
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.")
Output:
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.
Changed the code to also capture function's stderr.
Adding the [Python 3.Docs]: subprocess - Subprocess management based variant (which works too on my side). This needs an additional script (cpp_wrapper.py, which relies on cpp.py from above).
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.")
Output:
[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.
Upvotes: 0