新手 关于 Python 协程的一个问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
IVeverKB
V2EX    Python

新手 关于 Python 协程的一个问题

  •  
  •   IVeverKB 2020-12-07 11:27:01 +08:00 2929 次点击
    这是一个创建于 1852 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大概意思是这样的,协程里面有一个无线循环 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") 
    14 条回复    2020-12-07 22:54:12 +08:00
    111111111111
        1
    111111111111  
       2020-12-07 11:36:08 +08:00 via Android
    因为实际上是单线程的,下面的 while 要等上面的代码执行完了才有机会执行。
    或许可以试试 yield 关键字?

    你说的“不想把 B 写进另一个协程或线程里,我只想让它保留在主进程这个地方” 你可以说说具体的原因,这里只有一个进程一个线程,没什么主不主的
    sujin190
        2
    sujin190  
       2020-12-07 11:39:50 +08:00
    把 B 也用协程就是了啊,协程调度本来就独占整个线程的
    Vegetable
        3
    Vegetable  
       2020-12-07 11:41:14 +08:00
    按你说的没办法,你这个设计有问题,要不就 A 进独立线程,要不就 ab 都在一个 event loop 里
    fasionchan
        4
    fasionchan  
       2020-12-07 11:45:35 +08:00
    协程需要由事件循环驱动,如果主线程执行了事件循环,就没有机会执行外部的 while True,如果执行了 while True,就无法执行事件循环。
    IVeverKB
        5
    IVeverKB  
    OP
       2020-12-07 11:54:02 +08:00
    @111111111111 #1
    @sujin190 #2
    我是把业务需求简化了才这么说的。现在是想要在 django 启动的时候开一个协程或线程同时处理一下其他事情,django 本身对我来说就相当于 B 循环,所以我就这么问了。实际上是我不会把 B,也就是 django 本身业务写成一个协程。不知道这么说容易理解不。
    IVeverKB
        6
    IVeverKB  
    OP
       2020-12-07 11:58:17 +08:00
    @Vegetable #3
    @fasionchan #4
    感谢,明白了协程肯定做不了这个了
    NeilWang
        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 中处理视图逻辑时也是可以提交协程任务到事件循环的
    IVeverKB
        8
    IVeverKB  
    OP
       2020-12-07 14:51:58 +08:00
    @NeilWang #7
    非常感谢!提供了新思路,这个想法也太妙了哈哈
    keepeye
        9
    keepeye  
       2020-12-07 15:00:27 +08:00
    A 也转换成异步的 然后 asyncio.gather(A(), B())

    A 里面 sleep 换成 asyncio.sleep
    no1xsyzy
        10
    no1xsyzy  
       2020-12-07 15:08:17 +08:00
    我怀疑你应当寻求 Celery 一类任务框架

    顺便一提,loop.run_forever() 本身就可以理解为一个 while 循环。
    sujin190
        11
    sujin190  
       2020-12-07 15:33:21 +08:00
    @IVeverKB #5 你需要的是 celery
    IVeverKB
        12
    IVeverKB  
    OP
       2020-12-07 16:51:22 +08:00
    @NeilWang #7
    能否再追问一下,这个子线程写在 django 项目的哪个文件中比较好呢,就是能做到不影响 django 本项目的运行但同时还能被顺利执行到(且只会被执行一次,因为之前有看到写在 urls.pyviews.py 中会因为部署在 uwsgi+nginx 而产生多进程执行多次)?目前两个备选,一个是 project 目录下的__init__.py 文件,或者是 wsgi.py 文件,不知道是否满足我的需求?
    ClericPy
        13
    ClericPy  
       2020-12-07 22:04:54 +08:00
    交替执行... 两个任务的话, 办法挺多的, yield 生成器 / 或者互相 yield / asyncio.Event, 但是具体哪个能用还是看具体场景, 你这例子都没举全, 也没法给你调试个代码出来
    SaltCat
        14
    SaltCat  
       2020-12-07 22:54:12 +08:00
    用 asyncio.Lock,还有就直接 asyncio 技术栈一把嗦吧,asyncio 的侵入性感觉还是太强了。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1258 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 16:52 PVG 00:52 LAX 08:52 JFK 11:52
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86