我对如何在python/twisted中编写异步代码感到有点困惑.假设(为了论证)我向世界公开一个函数,它接受一个数字并返回True/False,如果它是素数/非素数,所以它看起来像这样模糊:
def IsPrime(numberin):
for n in range(2,numberin):
if numberin % n == 0: return(False)
return(True)
Run Code Online (Sandbox Code Playgroud)
(只是为了说明).
现在假设有一个网络服务器需要根据提交的值调用IsPrime.这需要很长时间才能完成numberin.
如果同时另一个用户请求一个小数的素数,有没有办法使用reactor/deferreds架构异步运行两个函数调用,以便在长计算结果之前返回短计算结果?
我知道如果IsPrime功能来自我的网络服务器将执行延迟的getPage的其他一些网络服务器,该怎么做呢,但如果它只是一个本地功能呢?
即,可以在两次调用IsPrime之间以某种方式进行Twisted时间共享,还是需要显式调用新线程?
或者,IsPrime循环是否需要分成一系列较小的循环,以便控制可以快速传递回反应堆?
或者是其他东西?
我有一个long_task运行大量cpu绑定计算的函数,我希望通过使用新的asyncio框架使其异步.生成的long_task_async函数使用a ProcessPoolExecutor将工作卸载到不同的进程,不受GIL约束.
麻烦的是,由于某种原因,concurrent.futures.Future实例ProcessPoolExecutor.submit从投掷时返回a TypeError.这是设计的吗?那些期货与asyncio.Future班级不兼容吗?什么是解决方法?
我也注意到发电机不是可拣选的,所以提交一个couroutine ProcessPoolExecutor就会失败.这个也有任何清洁的解决方案吗?
import asyncio
from concurrent.futures import ProcessPoolExecutor
@asyncio.coroutine
def long_task():
yield from asyncio.sleep(4)
return "completed"
@asyncio.coroutine
def long_task_async():
with ProcessPoolExecutor(1) as ex:
return (yield from ex.submit(long_task)) #TypeError: 'Future' object is not iterable
# long_task is a generator, can't be pickled
loop = asyncio.get_event_loop()
@asyncio.coroutine
def main():
n = yield from long_task_async()
print( n )
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud) 我正在使用Python 3 asyncio框架评估不同的模式以定期执行(实际的睡眠/延迟以简化),我有两段代码表现得很差,我无法解释原因.yield from正如我所料,第一个版本用于递归调用自身耗尽大约1000次迭代的堆栈.第二个版本递归调用协程,但委托实际的事件循环执行到asyncio.async并且不会耗尽堆栈.你能详细解释为什么第二个版本没有使用堆栈吗?执行此协程的两种方式有什么区别?
第一版(收益率):
@asyncio.coroutine
def call_self(self, i):
print('calling self', i)
yield from self.call_self(i + 1)
Run Code Online (Sandbox Code Playgroud)
第二个版本(asyncio.async):
@asyncio.coroutine
def call_self(self, i):
print('calling self', i)
asyncio.async(self.call_self(i + 1))
Run Code Online (Sandbox Code Playgroud)