Python Twisted:使代码无阻塞

Python Twisted:使代码无阻塞,python,asynchronous,twisted,blocking,Python,Asynchronous,Twisted,Blocking,我对如何用python/twisted编写异步代码有点困惑。假设(为了参数起见)我向世界公开了一个函数,它将接受一个数字,如果它是素数/非素数,则返回True/False,因此它看起来大致如下: def IsPrime(numberin): for n in range(2,numberin): if numberin % n == 0: return(False) return(True) (只是举例说明) 现在让我们假设有一个Web服务器需要根据提交的值调

我对如何用python/twisted编写异步代码有点困惑。假设(为了参数起见)我向世界公开了一个函数,它将接受一个数字,如果它是素数/非素数,则返回True/False,因此它看起来大致如下:


def IsPrime(numberin):
    for n in range(2,numberin):
        if numberin % n == 0: return(False)
    return(True)
(只是举例说明)

现在让我们假设有一个Web服务器需要根据提交的值调用iPrime。对于大型
数字
,这将需要很长时间

如果同时另一个用户要求一个小数字的素性,是否有方法使用reactor/deferreds架构异步运行两个函数调用,以便在长计算的结果之前返回短计算的结果

如果iPrime功能来自其他Web服务器(我的Web服务器将对其执行延迟的getPage),我理解如何执行此操作,但如果它只是一个本地功能呢

i、 例如,Twisted可以在对iPrime的两次调用之间以某种方式共享时间,还是需要显式调用新线程

或者,是否需要将iPrime循环分为一系列较小的循环,以便快速将控制传递回反应堆


还是别的什么?

我认为你目前的理解基本上是正确的。Twisted只是一个Python库,您为使用它而编写的Python代码会像您期望的Python代码那样正常执行:如果您只有一个线程(和一个进程),那么一次只发生一件事。Twisted几乎没有提供任何API来创建新的线程或进程,因此在正常过程中,代码按顺序运行<代码>iPrime在完成第一次执行之前,无法执行第二次

仍然只考虑一个线程(和一个进程),Twisted的所有“并发性”或“并行性”都来自这样一个事实,即Twisted提供了以非阻塞方式执行操作的工具,而不是执行阻塞网络I/O(和某些其他阻塞操作)。这样,当程序在等待阻塞I/O操作(如从套接字读取或写入套接字)完成时,它可能会被卡住而不执行任何操作时,可以继续执行其他工作

通过将它们分割成小块并让事件处理程序在这些小块之间运行,可以使事情“异步”。如果转换不会使代码更难理解和维护,那么这有时是一种有用的方法。Twisted为安排这些工作块提供了帮助。使用此帮助器是有益的,因为它可以根据所有不同的工作源做出调度决策,并确保有剩余的时间来服务事件源,而不会产生显著的额外延迟(换句话说,添加到它的作业越多,每个作业得到的时间就越少,这样反应器就可以继续工作)

Twisted还提供了几个用于处理线程和进程的API。如果不清楚如何将作业分解成块,则这些方法可能很有用。您可以使用在线程池中运行(线程安全!)函数。方便的是,此API返回一个函数,该函数最终将使用该函数的返回值触发(或者如果函数引发异常,则使用
失败
)。这些延迟看起来与其他延迟类似,就使用它们的代码而言,它也可以从调用中恢复过来,就像一个不使用额外线程、只使用非阻塞I/O和事件处理程序的函数一样


由于Python并不适合在单个进程中运行多个CPU绑定线程,Twisted还提供了一个非阻塞API来启动子进程并与之通信。您可以将计算转移到这些进程中,以利用额外的CPU或内核,而不必担心GIL会让您慢下来,这是分块策略和线程方法都无法提供的。处理此类流程的最低级别API是。还有一个软件包,它将为您管理一个进程池,并为进程提供一个类似于
deferToThread

当您有一个真正需要花费大量时间的函数时,例如,它是“阻塞”,您可以使用
deferToThread()
在线程中运行它:或者Twisted的进程支持:哈,我最近为Node.js编写了一个。有兴趣了解Twisted中的解决方案。