专栏首页Pou光明停止、暂停和恢复python解释器

停止、暂停和恢复python解释器

经过前面的一系列铺垫,现在要迎来我们的终极成果了——在运行我们自定义的函数过程中,如果要停止、暂停和再恢复python解释器,应该如何操作呢?

如果自定义函数中有耗时操作应该如何处理呢?

如何通过python c api实现钩子的功能呢?

先上码:

int PythonRunner::tracer(PyObject *, _frame *, int, PyObject *)

{

//Pause is requested...

if (_instance->pauseRequested())

{

Py_BEGIN_ALLOW_THREADS;

//If we are paused and no resume has been requested sleep

while (!_instance->resumeRequested())

{

QThread::msleep(500);

}

Py_END_ALLOW_THREADS;

}

//Abort requested

else if (true == _instance->interruptRequested())

{

Py_AddPendingCall(&PythonRunner::raiseException, NULL);

}

// Otherwise proceed normally.

return 0;

}

int PythonRunner::raiseException(void *)

{

// PyErr_SetInterrupt();

PyErr_SetString(PyExc_KeyboardInterrupt, "Abort");

return -1;

}

void PythonRunner::run()

{

PyEval_SetTrace(PythonRunner::tracer, NULL);

runPython();

}

static int tracer(PyObject *, struct _frame *, int, PyObject *);

static int raiseException(void *);

由于整个工程的代码贴上去会比较乱,只把主要的部分说下。

static int tracer(PyObject *, struct _frame *, int, PyObject *)该函数被用于注册回调, 用它可以实现钩子的功能。啥是钩子?简单来说就是执行每行代码前都会进入这个回调函数。注意struct _frame该结构体,需要包含#include <python3.5/frameobject.h>这个头文件,否则会报错。暂停、恢复和停止的功能也是在该函数中实现的。

我们知道在终端上运行python时,可以通过ctrl + c 来终止运行的python脚本,并且会弹出很多信息。我们的停止功能和这个相同,不过还有另一种接口调用。停止功能的函数需要返回-1,,并且调用PyErr_SetInterrupt()或PyErr_SetString(PyExc_KeyboardInterrupt, "Abort")。调用第一个是直接停止python解释器,不带有返回信息;调用第二个相当于使用ctrl + c来终止程序,带有返回信息,对用户输出内容这里包含About。异常停止的函数由c api Py_AddPendingCall()来调用。这里需要注意的是Py_AddPendingCall()该函数需要和python执行PyRun_SimpleString()的调用在同一个线程里面。

暂停的功能则是在调用每条指令前进行拦截。

为了防止自定义python中执行while 耗时操作,故将PyRun_SimpleString()放在线程中执行,这样就不会阻塞UI界面了。而我们也将回调函数注册到了线程里面。

这里面要注意的是当停止按钮按下后,被中断的线程需要根据对应的业务逻辑做对应的处理,有关线程的处理是很有考究的。

本文分享自微信公众号 - Pou光明(pou0230),作者:PouG

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Windows 嵌入python解释器

    这次主要记录在windows下嵌入python解释器的过程,程序没有多少,主要是头文件与库文件的提取。

    用户5908113
  • Qt5.12 + OpenGL 着色器

    https://learnopengl-cn.github.io/01%20Getting%20started/05%20Shaders/

    用户5908113
  • Qt Socket Server 收发JSON

    之前文章写过Linux C Socket 收发Json数据,最近用Qt Server实现了一遍。给我自己的感觉就是cJSON接口与Qt封装的一些接口是共通的:Q...

    用户5908113
  • 使用Pandas-Profiling加速您的探索性数据分析

    在第一次导入新数据集时,首先要做的是了解数据。这包括确定特定预测变量的范围,识别每个预测变量的数据类型以及计算每个预测变量的缺失值的数量或百分比等步骤。

    代码医生工作室
  • 如何用PyTorch进行语义分割?一个教程教会你|资源

    正值PyTorch 1.7更新,那么我们这次便给大家带来一个PyTorch简单实用的教程资源:用PyTorch进行语义分割。

    OpenCV学堂
  • 用PyTorch进行语义分割

    正值PyTorch 1.7更新,那么我们这次便给大家带来一个PyTorch简单实用的教程资源:用PyTorch进行语义分割。

    公众号机器学习与生成对抗网络
  • 网络协议 22 - RPC 协议(下)- 二进制类 RPC 协议

        前面我们认识了两个常用文本类的 RPC 协议,对于陌生人之间的沟通,用 NBA、CBA 这样的缩略语,会使得协议约定非常不方便。

    北国风光
  • [开发]Python实现运维监控服务器硬

          今天通过使用Python开发针对服务器硬件运行状态的监控,简单了解下在虚拟环境中的运维监控的实现,算是给全面研究云计算开一个头。

    py3study
  • 【leetcode刷题】T202-最少移动次数使数组元素相等 II

    https://leetcode-cn.com/problems/minimum-moves-to-equal-array-elements-ii/

    木又AI帮
  • 快速学习-EVM指令集

    cwl_java

扫码关注云+社区

领取腾讯云代金券