【发布时间】:2019-09-17 05:18:32
【问题描述】:
我对 Python asyncio 还是很陌生,所以我试图将我使用多线程解决的一个简单问题转换为使用 asyncio。
我举了一个例子来说明我想要实现的目标。
每个 MiniBot 实例都可以在随机时间启动(main 中的 time.sleep() 调用表示在不可预测时间的实例化。)
如果每个 MiniBot 在其他人完成之前启动,我希望它们能够并行运行。
多线程很好,但是当我用异步协程翻译问题时,我无法让它们一起开始。
我可以使用gather,但这需要在开始时完成所有任务,而我没有。
有什么建议吗?
谢谢
哦,是的,我使用的是 Python 3.6
多线程版本
import threading
import time
class MiniBot(object):
def __init__(self, _id:str):
self._id = _id
self.alive = True
self.start_time = time.time()
self.th = threading.Thread(target=self.run)
self.internal_state = 0
def _foo(self):
self.internal_state += 1
def run(self):
while self.alive:
self._foo()
if time.time() - self.start_time > 4:
print(f"Killing minibot: {self._id}")
print(f"Var is: {self.internal_state}")
self.stop()
time.sleep(0.1)
def start(self):
print(f"Starting Minibot {self._id}")
self.th.start()
def stop(self):
self.alive = False
if __name__ == "__main__":
# MiniBots activities start at random times but should coexist
MiniBot('a').start()
time.sleep(2)
MiniBot('b').start()
time.sleep(1.5)
MiniBot('c').start()
输出:
Starting Minibot a
Starting Minibot b
Starting Minibot c
Killing minibot: a
Var is: 40
Killing minibot: b
Var is: 40
Killing minibot: c
Var is: 40
异步版本(表现不如我所愿)
import asyncio
import time
class MiniBot(object):
def __init__(self, _id:str):
self._id = _id
self.alive = True
self.last_event = time.time()
self.internal_state = 0
async def _foo(self):
self.internal_state += 1
asyncio.sleep(2)
async def run(self):
while self.alive:
await self._foo()
if time.time() - self.last_event > 4:
print(f"Killing minibot: {self._id}")
print(f"Var is: {self.internal_state}")
self.stop()
asyncio.sleep(0.1)
def start(self):
print(f"Starting Minibot {self._id}")
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
loop.run_until_complete(self.run())
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
def stop(self):
self.alive = False
if __name__ == "__main__":
# MiniBots activities start at random times but should coexist
MiniBot('a').start()
time.sleep(2)
MiniBot('b').start()
time.sleep(1.5)
MiniBot('c').start()
输出:
Starting Minibot a
Killing minibot: a
Var is: 2839119
Starting Minibot b
Killing minibot: b
Var is: 2820634
Starting Minibot c
Killing minibot: c
Var is: 2804579
【问题讨论】:
-
您需要运行异步循环。并使用带有超时的 asyncio.wait 或 create_task 来启动每个机器人。顺便说一句,只需将它们全部启动并收集并让它们最初入睡。我会帮你,但我开车去上班..
-
谢谢@Pynchia,但这并不能解决问题。正如我所提到的,我不能使用
gather,因为 MiniBot 的数量和它们需要启动的时间是未知的。主程序启动并无限期运行,当特定事件发生时,我启动一个新的 MiniBot。 -
我认为你应该提高你的问题的质量,因为我看到你对你得到的优秀答案不满意
-
如果有帮助,请查看this recent answer of mine 来解决类似问题
-
如果您指的是您的答案,在我的问题中我实际上已经指定:“我可以使用收集,但这需要在开始时完成所有任务”。如果您指的是 user4815162342 的回答.. 那么这是另一个故事
标签: python python-asyncio python-multithreading