状态模式和事件触发切换状态可以整合什么库来做 Python 程序设计? - 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
oahebky

状态模式和事件触发切换状态可以整合什么库来做 Python 程序设计?

  •  
  •   oahebky Apr 30, 2020 3019 views
    This topic created in 2204 days ago, the information mentioned may be changed or developed.

    一个程序针对有(一堆) object(s) 的不同状态执行不同的 actions ( functions )。

    但是状态的切换是来自外部事件(非 http 请求,不过转换成 http 请求也 OK )触发。 外部事件触发可以做成 1. http 请求,2. 消息队列同步 等等

    手写一个状态模式应该不算问题,设计模式的实现大同小异。

    但是外部事件触发应该怎么做才好??? 就是用什么库写起来代码“很自然”。

    举个例子:

    比如我大学做过一个 MFC 应用,即,写的是 C++ 的桌面程序,点击按钮的事件触发 MFC 框架都生成做好了,然后只需要对按钮的 handler 函数编写实现即可。



    之所以有这个问题是因为我还没有怎么写过 python 的事件触发程序(非桌面程序,非 web 程序,一个后台 daemon 程序),所以不清楚“最佳实践”是怎么样的?

    10 replies    2020-05-04 11:41:45 +08:00
    ClericPy
        1
    ClericPy  
       Apr 30, 2020
    事件驱动用 pyee
    oahebky
        2
    oahebky  
    OP
       Apr 30, 2020
    @ClericPy #1 原文:“事件驱动用 pyee”
    ======
    回复:OK,我马上去了解一下。
    bwangel
        3
    bwangel  
       Apr 30, 2020
    https://github.com/jek/blinker

    blinker 可以用来定义事件。不过这个都是同步的。

    可以再描述一下详细需求么?内部状态切换是否是耗时较长任务,如果耗时较长,需要上队列。
    oahebky
        4
    oahebky  
    OP
       Apr 30, 2020
    @bwangel #3 原文:“https://github.com/jek/blinkerblinker 可以用来定义事件。不过这个都是同步的。可以再描述一下详细需求么?内部状态切换是否是耗时较长任务,如果耗时较长,需要上队列。”
    ======
    回复:一个 object 内有不同的状态,
    有的状态切换时间长(处于几小时,几天后的等待状态),有的状态切换时间短 - 计算或网络请求。

    简化状态其实也就是:

    状态 1 -> 状态 1 的行为 - 等待 -> 外部事件触发 => 切换到状态 2
    状态 2 -> 状态 2 的行为 - 计算得到结果 => 切换到状态 1

    就是切换状态不是单纯的状态模式里面的函数执行结束或者 sleep 就切换,
    而是来自外部的事件(其它 python 进程对它)触发,

    就是这一点不清楚选择什么样的库写起来比较不会重复造轮子。
    qile1
        6
    qile1  
       May 1, 2020 via Android
    感觉这个有点像微信公众号 回复消息的使用
    不过那个不会几个小时执行
    oahebky
        7
    oahebky  
    OP
       May 1, 2020
    @bwangel
    后来我思考了一下,对于我来说,使用哪种程序设计更像是程序是 C 端还是 S 端的问题。

    如果是 S 端的话(比如电脑桌面程序相对于用户性质上也是 S 端),那么使用你推荐的 blinker 应该是很好的选择(我把它 star 了,谢谢)。

    如果是 C 端的话,主要是一个请求主动发出去,等待响应。
    在我的实际情况上,更像 C 端。

    不过怎么做到异步是我正在研究的,因为 rabbitMQ 的 pika 和 aio-pika 我都还没好好使用过,之前只是了解到。
    oahebky
        8
    oahebky  
    OP
       May 1, 2020
    @brucedone
    这个库还在学怎么用,应该可以少写不少重复的代码。

    后来想了想,对于我自己的问题,难点在于怎么做到异步。
    当时提问的时候默认意思就是异步执行许多个具有状态模式设计的对象,原文没有说清楚;因为觉得解决了同步的状态模式循环,事件触发,就能加入 asyncio 迁移成异步。

    但是后来发现我就是不知道怎么做到不同的触发事件(非 sleep,非 http request )怎么 yield 出去,后来想来我应该主要是要解决学会 aio-pika 怎么使用的问题。
    bwangel
        9
    bwangel  
       May 4, 2020
    @oahebky

    感觉你这个状态切换的模型没必要用库,因为状态变更的逻辑你始终都是要写的,可以直接手撸一个。

    如果是 HTTP 请求触发的话,需要考虑一下并发问题,一个状态正在执行切换过程中,又有一个 HTTP 请求进来了。

    所以,建议

    当 HTTP 请求进来后,不立刻执行状态切换的操作,而是将它包装成一个事件,放到一个队列中,另外再起一个 Worker (可以用多个 Worker,根据你的实际情况确定,不会发生冲突即可),执行状态切换的操作。这样状态切换操作的执行时间过长,也不会有什么问题.


    事件+队列可以直接使用 RabbitMQ + Celery (千万别用 Redis+Celery,不成熟,有 bug)。如果觉得这两个太重,而业务量又不是太大的话,可以用 MySQL 自己写一个队列。
    oahebky
        10
    oahebky  
    OP
       May 4, 2020
    @bwangel
    这么设计这个程序我想了几天了(自己业余为了学习做项目),重新学了学 python 异步,可以说得出的结论和你完全一致。

    其实我最初是在纠结怎么在单个异步线程中,创建的以万为单位的(含有状态切换的)对象之间调度。
    后来发现要用 rabbitmq 的话,相当于要创建出同数量的 queue ;
    否则的话就要自己造一个基于对象 ID 的 loop 库 -- 对含有 ID 的 message 用 gener.send(msg) 激活对应的 gener 。

    不论哪种方式都有些过度了。

    所以还是读到带 ID 的 message 之后,重新创建对象,执行完任务销毁对象,loop 回去等待消息队列;这样设计目前来看是合理的。
    About     Help     Advertise     Blog     API     FAQ     Solana     5662 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 1919ms UTC 03:37 PVG 11:37 LAX 20:37 JFK 23:37
    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