Python 从普通函数调用协程
Python calling coroutine from normal function
所以我有一个倒计时脚本,看起来像这样:
import time, threading, asyncio
def countdown(n, m):
print("timer start")
time.sleep(n)
print("timer stop")
yield coro1
async def coro1():
print("coroutine called")
async def coromain():
print("first")
t1 = threading.Thread(target=countdown, args=(5, 0))
t1.start()
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain())
loop.stop()
我想要它做的很简单:
Run coromain
Print "first"
Start thread t1, print "timer start" and have it wait for 5 seconds
In the mean time, print "second"
after 5 seconds, print "timer stop"
exit
但是,当我 运行 这段代码输出时:
Run coromain
Print "first"
Print "second"
exit
我很困惑为什么要这样做。谁能解释一下我在这里做错了什么?
经过一番挖掘,制定了此解决方法。它可能不漂亮,但它有效:
import time, threading, asyncio
def countdown(n, m):
print("timer start")
time.sleep(n)
print("timer stop")
looptemp = asyncio.new_event_loop()
asyncio.set_event_loop(looptemp)
loop2 = asyncio.get_event_loop()
loop2.run_until_complete(coro1())
loop2.close()
async def coro1():
print("coroutine called")
async def coromain():
print("first")
t1 = threading.Thread(target=countdown, args=(5, 0))
t1.start()
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain())
loop.stop()
不幸的是,它不适用于我的特定用例,但我认为它可能有用。
这取决于您的问题是否是施加额外约束的更大问题的一部分,但我看不出使用 threading
的理由。相反,您可以在同一个事件循环中使用两个单独的 Task
s 运行,这是异步编程的要点之一:
import asyncio
async def countdown(n, m): # <- coroutine function
print("timer start")
await asyncio.sleep(n)
print("timer stop")
await coro1()
async def coro1():
print("coroutine called")
async def coromain():
print("first")
asyncio.ensure_future(countdown(5, 0)) # create a new Task
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain()) # run coromain() from sync code
pending = asyncio.Task.all_tasks() # get all pending tasks
loop.run_until_complete(asyncio.gather(*pending)) # wait for tasks to finish normally
输出:
first
second
timer start
(5 second wait)
timer stop
coroutine called
当使用 ensure_future
时,您有效地在单个 OS 的线程中创建了一个新的“执行线程”(参见纤维)。
所以我有一个倒计时脚本,看起来像这样:
import time, threading, asyncio
def countdown(n, m):
print("timer start")
time.sleep(n)
print("timer stop")
yield coro1
async def coro1():
print("coroutine called")
async def coromain():
print("first")
t1 = threading.Thread(target=countdown, args=(5, 0))
t1.start()
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain())
loop.stop()
我想要它做的很简单:
Run coromain
Print "first"
Start thread t1, print "timer start" and have it wait for 5 seconds
In the mean time, print "second"
after 5 seconds, print "timer stop"
exit
但是,当我 运行 这段代码输出时:
Run coromain
Print "first"
Print "second"
exit
我很困惑为什么要这样做。谁能解释一下我在这里做错了什么?
经过一番挖掘,制定了此解决方法。它可能不漂亮,但它有效:
import time, threading, asyncio
def countdown(n, m):
print("timer start")
time.sleep(n)
print("timer stop")
looptemp = asyncio.new_event_loop()
asyncio.set_event_loop(looptemp)
loop2 = asyncio.get_event_loop()
loop2.run_until_complete(coro1())
loop2.close()
async def coro1():
print("coroutine called")
async def coromain():
print("first")
t1 = threading.Thread(target=countdown, args=(5, 0))
t1.start()
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain())
loop.stop()
不幸的是,它不适用于我的特定用例,但我认为它可能有用。
这取决于您的问题是否是施加额外约束的更大问题的一部分,但我看不出使用 threading
的理由。相反,您可以在同一个事件循环中使用两个单独的 Task
s 运行,这是异步编程的要点之一:
import asyncio
async def countdown(n, m): # <- coroutine function
print("timer start")
await asyncio.sleep(n)
print("timer stop")
await coro1()
async def coro1():
print("coroutine called")
async def coromain():
print("first")
asyncio.ensure_future(countdown(5, 0)) # create a new Task
print("second")
loop = asyncio.get_event_loop()
loop.run_until_complete(coromain()) # run coromain() from sync code
pending = asyncio.Task.all_tasks() # get all pending tasks
loop.run_until_complete(asyncio.gather(*pending)) # wait for tasks to finish normally
输出:
first
second
timer start
(5 second wait)
timer stop
coroutine called
当使用 ensure_future
时,您有效地在单个 OS 的线程中创建了一个新的“执行线程”(参见纤维)。