大概意思是这样的,协程里面有一个无线循环 A,主进程也就是下面写的 print main loop 是个无线循环 B 。有没有什么方法是 A 和 B 循环可以交替执行的?因为我现在发现只有让 A 一直跑或者 A 做完了才能做 B,但是因为它们俩都是死循环就没法实现同时交替执行。
或者是不是我要实现 A 和 B 交替循环只有把 A 写成多线程才行?前提是我不想把 B 写进另一个协程或线程里,我只想让它保留在主进程这个地方。
多谢
import asyncio
import time
async def my_async():
while True:
await asyncio.sleep(0.5)
print("in my_async loop")
loop = asyncio.get_event_loop()
loop.crate_task(my_async())
loop.run_forever()
#loop.run_until_complete(my_async())
while True:
time.sleep(0.5)
print("in the main loop")
1
111111111111 2020-12-07 11:36:08 +08:00 via Android
因为实际上是单线程的,下面的 while 要等上面的代码执行完了才有机会执行。
或许可以试试 yield 关键字? 你说的“不想把 B 写进另一个协程或线程里,我只想让它保留在主进程这个地方” 你可以说说具体的原因,这里只有一个进程一个线程,没什么主不主的 |
2
sujin190 2020-12-07 11:39:50 +08:00
把 B 也用协程就是了啊,协程调度本来就独占整个线程的
|
3
Vegetable 2020-12-07 11:41:14 +08:00
按你说的没办法,你这个设计有问题,要不就 A 进独立线程,要不就 ab 都在一个 event loop 里
|
4
fasionchan 2020-12-07 11:45:35 +08:00
协程需要由事件循环驱动,如果主线程执行了事件循环,就没有机会执行外部的 while True,如果执行了 while True,就无法执行事件循环。
|
5
IVeverKB OP @111111111111 #1
@sujin190 #2 我是把业务需求简化了才这么说的。现在是想要在 django 启动的时候开一个协程或线程同时处理一下其他事情,django 本身对我来说就相当于 B 循环,所以我就这么问了。实际上是我不会把 B,也就是 django 本身业务写成一个协程。不知道这么说容易理解不。 |
6
IVeverKB OP |
7
NeilWang 2020-12-07 12:27:29 +08:00
真的想使用协程运行任务 A 的话,其实可以在 django 启动前启动一个子线程,在子线程中创建一个新的事件循环,然后把协程 A 在这个事件循环里运行。
``` import asyncio import time import threading async def my_async(): while True: await asyncio.sleep(0.5) print("in my_async loop") _event_loop = asyncio.new_event_loop() def run_event_loop(): _event_loop.run_forever() threading.Thread(target=_event_loop.run_forever, daemon=True).start() # 将新的事件循环设置为当前线程的事件循环,这样后续在当前线程中可以使用 asyncio.get_event_loop() 得到 _event_loop asyncio.set_event_loop(_event_loop) # 事件循环不在当前线程,需要使用 run_coroutine_threadsafe 提交协程任务 asyncio.run_coroutine_threadsafe(my_async(), asyncio.get_event_loop()) while True: time.sleep(0.5) print("in the main loop") ``` 这样的话,在 django 中处理视图逻辑时也是可以提交协程任务到事件循环的 |
9
keepeye 2020-12-07 15:00:27 +08:00
A 也转换成异步的 然后 asyncio.gather(A(), B())
A 里面 sleep 换成 asyncio.sleep |
10
no1xsyzy 2020-12-07 15:08:17 +08:00
我怀疑你应当寻求 Celery 一类任务框架
顺便一提,loop.run_forever() 本身就可以理解为一个 while 循环。 |
12
IVeverKB OP @NeilWang #7
能否再追问一下,这个子线程写在 django 项目的哪个文件中比较好呢,就是能做到不影响 django 本项目的运行但同时还能被顺利执行到(且只会被执行一次,因为之前有看到写在 urls.py 、views.py 中会因为部署在 uwsgi+nginx 而产生多进程执行多次)?目前两个备选,一个是 project 目录下的__init__.py 文件,或者是 wsgi.py 文件,不知道是否满足我的需求? |
13
ClericPy 2020-12-07 22:04:54 +08:00
交替执行... 两个任务的话, 办法挺多的, yield 生成器 / 或者互相 yield / asyncio.Event, 但是具体哪个能用还是看具体场景, 你这例子都没举全, 也没法给你调试个代码出来
|
14
SaltCat 2020-12-07 22:54:12 +08:00
用 asyncio.Lock,还有就直接 asyncio 技术栈一把嗦吧,asyncio 的侵入性感觉还是太强了。。。
|