python在线程中的exec脚本中中断无限循环

标签 python asynchronous abort

GUI 应用程序允许用户编写 Python 脚本,然后运行它(通过 exec)。问题是如果用户错误(我不关心恶意,只是用户的诚实编码错误)脚本包含无限循环,控制将永远不会返回到我的应用程序。由于 GUI,键盘中断不起作用。

我已经确定了四种处理方法:

  1. 跟踪:使用 sys.settrace 以便在每一行调用一个函数;在那里,我可以放置逻辑来尝试确定同一段代码是否正在一遍又一遍地执行(我还不知道这在实践中会有多大的挑战性)。我猜这可能会大大降低执行速度。
  2. 异步异常:在单独的线程中运行脚本,并使用 ctypes 让主线程使用 PyThreadState_SetAsyncExc 在脚本线程中引发异常以将其踢出循环(参见 https://gist.github.com/liuw/2407154http://tomerfiliba.com/recipes/Thread2/ )。然后调用 exec 的线程部分将恢复控制并可以采取适当的操作(向用户显示消息等)。我知道,不应从外部中止线程,但在这里,即使这样做会使脚本更改的对象处于未定义状态,至少它会允许 GUI 丢弃不再可靠的对象(它可以做到这一点,因为脚本可访问的所有修改都在一个大对象中,可以将其丢弃并从磁盘重新加载)。
  3. Separate process:使用 multiprocessing 模块,将在单独的进程中运行脚本;然而,脚本可以包含对存在于父线程主线程中的对象的调用,因此这将变得非常复杂。
  4. 守护线程:在守护线程中运行脚本,然后如果脚本在一段时间后没有返回,则认为它“挂起”。当应用程序退出时,线程将继续运行,用户可以通过任务管理器强制终止它(或者退出的线程可以,通过引发 SystemException 等)。

那么问题来了:如果我必须提供此功能,那么以上方法中哪一种是万恶之轻?除了上述 4 种之外,还有其他技术吗?

最佳答案

一种方法是使用自定义 multiprocessing.Manager 对象。它可以为您处理同步。 (链接:multiprocessing)

这是一个拥有单个实例的示例,多进程进程能够在其上调用方法。注意我没有使用实例状态,这留给读者:)

原始代码将“maths.add”(实例方法)传递给池,但方法不可挑选。因此,我创建了全局“my_add”,它接受一个数学实例(可选取的),然后将一些数字加在一起并得出结果。

来源

from multiprocessing import Pool
from multiprocessing.managers import BaseManager

class MathsClass(object):
    def add(self, x, y):
        return x + y
    def mul(self, x, y):
        return x * y

class MyManager(BaseManager):
    pass

MyManager.register('Maths', MathsClass)

def my_add(mobj, *args):
    return mobj.add(*args)

if __name__ == '__main__':
    manager = MyManager()
    manager.start()
    maths = manager.Maths()

    # pass the shared 'maths' object into each process

    pool = Pool()
    print pool.apply(my_add, [maths, 4, 3])
    # print maths.add(4, 3)         # prints 7
    print pool.apply(my_add, [maths, 7, 8])
    # print maths.mul(7, 8)         # prints 56

输出

7
15

关于python在线程中的exec脚本中中断无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25365471/

相关文章:

multithreading - 在 segue 之前等待异步方法

' ' : free(): invalid pointer 中的 C++ 错误

python - Keras my_layer.output 返回 KerasTensor 对象而不是 Tensor 对象(在自定义损失函数中)

python - 是否可以将 pipenv 与 setup.py 一起使用?

python - youtube-dl python 库文档

c# - 如何使用 Task.WhenAny 和 ReadLineAsync 从任何 TcpClient 获取数据

python - 为什么基于 iLocation 的 bool 索引不起作用?

c# - 异步调用同步方法

android - GetStringUTFChars 中的 dvmDecodeIndirectRef 中的 dvmAbort

c++ - 不可避免地调用 abort() 可能会产生什么影响?