PEP 0492增加了新的__await__魔法.实现此方法的对象变为类似未来的对象,可以等待使用await.很明显:
import asyncio
class Waiting:
def __await__(self):
yield from asyncio.sleep(2)
print('ok')
async def main():
await Waiting()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
好的,但如果我想调用一些已async def定义的函数而不是asyncio.sleep?我不能使用await因为__await__不是async函数,我无法使用yield from因为本机协同程序需要await表达式:
async def new_sleep():
await asyncio.sleep(2)
class Waiting:
def __await__(self):
yield from new_sleep() # this is TypeError
await new_sleep() # this is SyntaxError
print('ok')
Run Code Online (Sandbox Code Playgroud)
我该如何解决?
我对Python中的多线程有一个非常基本的理解,甚至是对它的基本理解asyncio.
我正在编写一个基于Curses的小程序(最终将使用完整的GUI,但这是另一个故事),它处理主线程中的UI和用户IO,然后有另外两个守护程序线程(每个都有自己的队列/工人方法 - 即-得到-东西从 - 一个队列):
watcher监视基于时间和条件(例如发布到留言板,收到消息等)事件的线程,然后将所需任务放入...worker)守护程序线程的队列然后完成它们.所有三个线程都在不断地同时运行,这引出了一些问题:
worker线程的队列(或者更一般地说,任何线程的队列)为空时,它应该被停止,直到有什么事情要做,或者是否可以继续运行?并发线程在除了查看队列之外没有做任何事情时会占用大量处理能力吗?watcher线程持续运行单个方法,我想worker线程将能够从watcher线程放入的单个队列中拉出任务.watcher线程连续这样运行?根据我的理解,请纠正我,如果我错了,asyncio应该用于基于事件的多线程,这似乎与我正在尝试做的相关.asyncio完美的情况,但是,我不确定.谢谢!
对于ASYNCIO文档给出了如何打印的"Hello World"每两秒钟两个例子: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio-hello-world-callback https://开头docs.python.org/3/library/asyncio-task.html#asyncio-hello-world-coroutine
我可以从解释器运行那些,但如果我这样做,我将无法访问解释器.是否可以在后台运行asyncio事件循环,以便我可以在解释器中输入命令?
我有一个非常小的测试程序,除了执行asyncio事件循环之外什么都不做:
import asyncio
asyncio.get_event_loop().run_forever()
Run Code Online (Sandbox Code Playgroud)
当我在Linux上运行此程序并按Ctrl+时C,程序将正常终止,但有KeyboardInterrupt异常.在Windows上按Ctrl+ C什么也没做(用Python 3.4.2测试).即使在Windows上,一个简单的无限循环也能正确time.sleep()引发KeyboardInterrupt:
import time
while True:
time.sleep(3600)
Run Code Online (Sandbox Code Playgroud)
为什么asyncio的事件循环会抑制Windows上的KeyboardInterrupt?
我已经阅读了大量有关Python的3.5异步/等待事物的文章和教程.我不得不说我很困惑,因为有些人使用get_event_loop()和run_until_complete(),有些人使用ensure_future(),有些人使用asyncio.wait(),有些人使用call_soon().
看起来我有很多选择,但我不知道它们是完全相同还是有使用循环的情况,有些情况下你使用wait().
但事情是所有的例子都与asyncio.sleep()真实的慢速操作的模拟一起工作,它返回一个等待的对象.一旦我尝试将这一行换成一些真正的代码,整个事情就会失败.上面介绍的方法与我应该如何运行尚未准备好进行异步/等待的第三方库之间存在差异.我确实使用Quandl服务来获取一些股票数据.
import asyncio
import quandl
async def slow_operation(n):
# await asyncio.sleep(1) # Works because it's await ready.
await quandl.Dataset(n) # Doesn't work because it's not await ready.
async def main():
await asyncio.wait([
slow_operation("SIX/US9884981013EUR4"),
slow_operation("SIX/US88160R1014EUR4"),
])
# You don't have to use any code for 50 requests/day.
quandl.ApiConfig.api_key = "MY_SECRET_CODE"
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
我希望你明白我的感受是多么的失落,以及我希望并行运行的简单方法.
我有一个python多线程应用程序.我想在一个线程中运行一个asyncio循环,并从另一个线程发送回调和协同程序.应该很容易,但我无法理解asyncio的东西.
我提出了以下解决方案,它可以完成我想要的一半,随意评论任何事情:
import asyncio
from threading import Thread
class B(Thread):
def __init__(self):
Thread.__init__(self)
self.loop = None
def run(self):
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop) #why do I need that??
self.loop.run_forever()
def stop(self):
self.loop.call_soon_threadsafe(self.loop.stop)
def add_task(self, coro):
"""this method should return a task object, that I
can cancel, not a handle"""
f = functools.partial(self.loop.create_task, coro)
return self.loop.call_soon_threadsafe(f)
def cancel_task(self, xx):
#no idea
@asyncio.coroutine
def test():
while True:
print("running")
yield from asyncio.sleep(1)
b.start()
time.sleep(1) #need to wait for loop to start
t …Run Code Online (Sandbox Code Playgroud) 澄清这个问题的原因:
使用两个具有相同名称的模块令人困惑.它们代表什么使它们与众不同?
什么任务可以解决另一个不能,反之亦然?
如何创建一个使芹菜任务看起来像的包装器asyncio.Task?或者有更好的方法将Celery与asyncio?
Celery的创建者@asksol 说:
在异步I/O框架之上使用Celery作为分布式层是很常见的(最重要的提示:将CPU绑定任务路由到prefork worker意味着它们不会阻止您的事件循环).
但我找不到专门针对asyncio框架的代码示例.
我想我得到了这个错误,因为我的代码调用了asyncio.get_event_loop().run_until_complete(foo())两次.从foo()第二次调用函数开始foo().我的问题是:为什么这会成为问题?我为什么要关心这个循环在运行?
对这个问题进行了编辑,我认为这个编辑模糊了(有些人更喜欢遵循规则而不理解它们,因此从标题中删除了"非法"字样).不幸的是,这会造成混乱.
我不会对错误提出这一事实感到惊讶.我可以追溯到asyncio源头,看看这个图书馆的作者想要这样做,那里没有神秘感.令人费解的部分原因在于库的作者认为在循环已经运行时从事件循环中请求运行某些函数是非法的.
我们可以将问题简化为两个这样的调用,通过案例分析,我们将看到这三种可能性:
现在,是否有任何明智的行为可以解决所有三种情况?对我而言,显而易见的是,这里可能存在或可能存在多种理智行为.例如:
run_until_complete()到第二个函数完成之后的第一个实例之后的代码(因此不会run_until_complete()执行后面的代码.run_until_complete忽略所有其他调用站点.现在,我可以理解这种行为可能不是每个人都想要的.但是,由于这个库决定让程序员控制启动/停止事件循环,它还应该满足这些决策的后果.使多次启动相同循环成为错误会使库代码无法执行此操作,从而降低了库利用的质量和实用性asyncio(例如,确实如此aiohttp).
我正在使用该websockets库在Python 3.4中创建一个websocket服务器.这是一个简单的echo服务器:
import asyncio
import websockets
@asyncio.coroutine
def connection_handler(websocket, path):
while True:
msg = yield from websocket.recv()
if msg is None: # connection lost
break
yield from websocket.send(msg)
start_server = websockets.serve(connection_handler, 'localhost', 8000)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Run Code Online (Sandbox Code Playgroud)
假设我们 - 另外 - 想要在某些事件发生时向客户端发送消息.为简单起见,让我们每隔60秒定期发送一条消息.我们怎么做?我的意思是,因为connection_handler经常等待收到的消息,服务器只能在收到客户端的消息后才采取行动,对吗?我在这里错过了什么?
也许这种情况需要一个基于事件/回调的框架,而不是一个基于协同程序的框架?龙卷风?
python ×10
python-asyncio ×10
python-3.x ×4
async-await ×2
asynchronous ×2
celery ×1
concurrency ×1
module ×1
python-3.4 ×1
python-3.5 ×1
websocket ×1
windows ×1