估计 C++ 中嵌入式 python 脚本的进度
Estimating progress of embedded python script in C++
简介
假设我有一个 C++ 应用程序,其中嵌入了 python 脚本。该脚本进行了一些繁重的计算,需要很长时间才能结束。完成后,我可以提取脚本的结果。然而,知道计算的实际停留时间是多少会很方便——目前是完成了 10% 还是一半的工作?这是一个示例代码(使用 boot python
):
app.cpp
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
int main()
try
{
Py_Initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("Script.py", name_space, name_space);
object MyFunc = name_space["MyFunc"];
object result = MyFunc();
double sum = extract<double>(sum);}
Py_Finalize();
Script.py
def MyFunc():
cont = 0
while (cont < 10000):
#...some calculations here, increasing "result" value on each step...
cont +=1
return result
问题
如果代码全部使用 C++,我可以使用 emit
等本机框架工具来访问 GUI 进度条槽,并更新其值。但是在上述情况下呢?在控制台应用程序中,我每次都可以直接从 python 打印 cont
。然而,它不是任何带有 GUI 的 C++ 的解决方案。有什么办法可以从 C++ 代码级别确定 Script.py
在循环的哪一圈执行?或者,也许有任何其他解决方案来提供进度条?
您可以将 python 程序的信号发送回 C++ 程序,例如:
if cont % 100 == 0:
os.kill(cpp_progs_pid, signal.SIGUSR1)
然后在 C++ 中为该信号使用信号处理程序以使用 emit
。
编辑:在您的 C++ 代码中,您需要传递程序的 pid,如下所示:
#include <sys/types.h>
...
int pid = getpid(); // python's cpp_progs_pid
exec_file("Script.py", name_space, name_space, pid);
还有这样的东西来处理信号:
#include <signal.h>
...
void my_handler(int signum)
{
if (signum == SIGUSR1)
{
// code to use emit
}
}
...
signal(SIGUSR1, my_handler); // set your signal handler
当您的 C++ 程序 运行 时,信号处理程序 my_handler
将被异步调用,因此您必须小心任何副作用。在调用 python 脚本之前,必须设置一次。
总结一下评论区的结论:
这个问题可以通过给从 python 调用的函数一个回调来解决。 .cpp 看起来像这样:
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
int main(){
Py_Initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("Script.py", name_space, name_space);
object MyFunc = name_space["MyFunc"];
object result = MyFunc();
double sum = extract<double>(sum);}
Py_Finalize();}
callback(int cont){
int cont_final = 10000;
double progr = cont / cont_final * 100;
cout << cont << "\n";}
请记住,回调必须是静态成员或自由函数(在本例中我展示了第二个选项)。如果您还需要传递状态(例如由于 GUI),请查看 .
Python 部分将是:
def MyFunc(callback):
cont = 0
while (cont < 10000):
#...some calculations here, increasing "result" value on each step...
cont +=1
callback(cont) #Here we call progress update
return result
就是这样 - 在结果中,从 0 到 100 的进度指示器将打印到控制台。
简介
假设我有一个 C++ 应用程序,其中嵌入了 python 脚本。该脚本进行了一些繁重的计算,需要很长时间才能结束。完成后,我可以提取脚本的结果。然而,知道计算的实际停留时间是多少会很方便——目前是完成了 10% 还是一半的工作?这是一个示例代码(使用 boot python
):
app.cpp
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
int main()
try
{
Py_Initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("Script.py", name_space, name_space);
object MyFunc = name_space["MyFunc"];
object result = MyFunc();
double sum = extract<double>(sum);}
Py_Finalize();
Script.py
def MyFunc():
cont = 0
while (cont < 10000):
#...some calculations here, increasing "result" value on each step...
cont +=1
return result
问题
如果代码全部使用 C++,我可以使用 emit
等本机框架工具来访问 GUI 进度条槽,并更新其值。但是在上述情况下呢?在控制台应用程序中,我每次都可以直接从 python 打印 cont
。然而,它不是任何带有 GUI 的 C++ 的解决方案。有什么办法可以从 C++ 代码级别确定 Script.py
在循环的哪一圈执行?或者,也许有任何其他解决方案来提供进度条?
您可以将 python 程序的信号发送回 C++ 程序,例如:
if cont % 100 == 0:
os.kill(cpp_progs_pid, signal.SIGUSR1)
然后在 C++ 中为该信号使用信号处理程序以使用 emit
。
编辑:在您的 C++ 代码中,您需要传递程序的 pid,如下所示:
#include <sys/types.h>
...
int pid = getpid(); // python's cpp_progs_pid
exec_file("Script.py", name_space, name_space, pid);
还有这样的东西来处理信号:
#include <signal.h>
...
void my_handler(int signum)
{
if (signum == SIGUSR1)
{
// code to use emit
}
}
...
signal(SIGUSR1, my_handler); // set your signal handler
当您的 C++ 程序 运行 时,信号处理程序 my_handler
将被异步调用,因此您必须小心任何副作用。在调用 python 脚本之前,必须设置一次。
总结一下评论区的结论: 这个问题可以通过给从 python 调用的函数一个回调来解决。 .cpp 看起来像这样:
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
int main(){
Py_Initialize();
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("Script.py", name_space, name_space);
object MyFunc = name_space["MyFunc"];
object result = MyFunc();
double sum = extract<double>(sum);}
Py_Finalize();}
callback(int cont){
int cont_final = 10000;
double progr = cont / cont_final * 100;
cout << cont << "\n";}
请记住,回调必须是静态成员或自由函数(在本例中我展示了第二个选项)。如果您还需要传递状态(例如由于 GUI),请查看
Python 部分将是:
def MyFunc(callback):
cont = 0
while (cont < 10000):
#...some calculations here, increasing "result" value on each step...
cont +=1
callback(cont) #Here we call progress update
return result
就是这样 - 在结果中,从 0 到 100 的进度指示器将打印到控制台。