作者HuangJC (吹笛牧童)
看板Python
标题Re: [问题] py程式之间的值如何传递
时间Thu Jan 26 10:51:09 2023
谢谢你的讨论,我好像看到适合我的东西 XD
我的例子是我要写出 sensor(比如读取温度计)
还有另外写出使用 sensor 值运作的程式
socket 我会写,但处理断线,timeout 的逻辑累死我了
後来我用 mqtt
除掉处理断线,timeout 等等问题
这种类似 call back 的逻辑给我另一种困扰, 比如
sensor.py 送出温度计值
然後 relay.py 就必需接收到这个值处理起来
但其实我不在乎温度计何时传值给我
我在乎的是最後一个值是什麽
比如五秒有五次更新值,反正我在第五秒才想处理
那前四次的值其实我不在乎,就让它消失吧..
用 mqtt 其实我就是在收到讯息时,on_message 自己维护一块记忆体先塞进去
何时要用此值,才去问那块记忆体
档案可以担此重任,用覆盖的就好
但不同程式间 multitask, 就不要写入端开档/清空,还没写入,读取端就来读耶
那我又有其他困扰了
》何时要用此值,才去问那块记忆体
Redis 不就替我做了这事
而且可以跨电脑
档案的话,不知有没有一定要关档(所以保证写入完毕),其他程式才能开档的检查
这问题在 multi-thread 里即使是记忆体变数,也是很常面对的
但用 python 我一直都不用理,因为 python 的多工有个 GIL 在,它的 ATOM 太大了
若在 C,我就吃了不少亏,常常要设 critical section
而 Redis 应该就是跨电脑很适合吧..
当有多台电脑跑 relay.py,
他们何时需要资料,就何时去问 sensor.py 那台电脑
而不是 sensor.py 经常主动推播,漏收讯息也不好
不想收,它也一直推给所有来注册的电脑
(喔,mqtt 采订阅制,不想收就不订阅,困扰没那麽大)
很值得我参考。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.204.157.162 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Python/M.1674701472.A.C2B.html
补上档案的问题
from time import sleep
file = 'output.txt'
with open(file, 'w') as f:
f.write('apple\n')
sleep(10)
f.write('banana\n')
这个例子是个极端做法,在写档中间插入等待十秒
在做 multi-thread/task 极端 debug 时,有时得这麽做
我们知道写档很快,但万一没那麽快时,有没有问题?
开启两个 terminal, 一个用命令列执行这个程式
(比如 python3 test.py)
要十秒後,游标才会掉下来
这时赶快去另一个 terminal 试 cat output.txt
十秒内,档案已经存在,但内容是空的
-------------
以前学微软的 SDK 时,关於开档,有更多参数可下
share read/write 限制等等
如果我不开 share, 基本上就是不共享了
(不知有没有记错;顶多记反,但确定有这个概念)
不共享的意思是,当有一个程序开了此档做写入
那麽别人就无法做读取
那这个 bug 也就不会发生
不然若我用档案当做 IPC 中介传递,在 a.py 写入时,恰好 b.py 要读取
那就会读到空档,怎麽办?
当然这状况很难发生,因为档案并不会写到十秒那麽久
但如果是一万次发生一次,也会让人头疼,bug 重制不易
所以刻意改变执行速度也是个技巧
要说我龟毛吗?
※ 编辑: HuangJC (49.217.46.86 台湾), 01/26/2023 16:02:43
1F:→ Arataki: Import watchdog to reopen socket time out or broken 01/26 15:58
抱歉,看不懂,可以给多一点资讯吗?谢谢
https://bbs.huaweicloud.com/blogs/325805
是像这个例子吗?
这例子不是我要的
它可以在档案改变时触发 event
於是就好像 call back
call back(或说 interrupt)的确有时对我有用
但比如有个温度计,sensor.py 每一秒去读它一次
我并不在乎何时读了并更新到 output.txt 里
我在乎的是,另一支程式,relay.py 要去取用档案里的温度值时
任何时候,我想读,就有目前的值;我只要最後一个值而已
因此新值不断覆盖旧值,我不在乎
但我在乎档案写到一半不能被读取时,很恰巧的我去读了...
所以我需要一些像是 critical section 这样的东西
但我想 redis 有做好这件事
※ 编辑: HuangJC (49.217.46.86 台湾), 01/26/2023 16:15:03
举个例子,共享的若是一个温度值,int or float, 问题不大
但若是一张相片,档案还真不小,写入需要时间,那问题就出来了
当然或许可以用写入 tmp file 然後 rename 的方式,减少空窗期
但还是有点机率去读到空图。。
※ 编辑: HuangJC (49.217.46.86 台湾), 01/26/2023 16:18:12
https://myapollo.com.tw/zh-tw/python-fcntl-flock/
找到了,用 flock 来做
麻烦到让我想。。运气不会那麽糟吧,不要做这些事 XDDDD
2F:→ DavisX: 有没考虑用EPICS去弄device并存入PV 再用PYEPICS去读 01/26 16:37
没看懂,什麽是 PV?
3F:→ Arataki: EPICS 牛刀杀小鸡,不过用它真的没问题,但是要先学会它 01/26 18:06
其实很早前我就觉得 mysql 可以用,只是它放硬碟,速度慢
而且我要自己建一个 table,里面是 name 对应 value
还要自己编码给各种资料型态
(value 用 text 就好,不管什麽 binary 都有法子编入 text
其实是很久前的工作,土法练钢,和主管玩过一次)
但有 redis 就蛮像在做这些事,只是别人做好了,不用自己打造轮子
我的负担是轻量化的,常是传送 int, float, 顶多一些 string
image 是故意压力测试的,其实我还想不到我有这需求
所以 redis 就够了
目前用 MQTT 也够了,就自己打造
方法是向 server 订阅後,server 只要更新,我都抓下来 local 存而不用
等要用时再去存放处拿资料
虽然多了些 code, 但是不会有资料被洗掉刚好拿到空资料这种事
(有这概念,就算用 socket 自己从头打造,也大概是这种样子)
EPICS 先别说学不学得会了,它专长在哪,为何要用它,我都比较不出来 XD
粒子加速器?望远镜? 用这种方法描述似乎不能让我看到重点
还是说'望远镜需要传大画面,所以这是能传大档,且符合我前面描述需求'的东西
那这样我算有听懂一些了
因为我的负担不大,所以。。那应该就是 redis 就好
然後 PV 是什麽?
※ 编辑: HuangJC (49.217.130.232 台湾), 01/26/2023 19:17:48
4F:→ Hsins: Process Variables 01/26 19:48
喔。。我的温度就是
说到 call back,我有的用得到
比如何时远端按键被按,或者脉冲式流量计
不过脉冲式流量计我会倾向於在 sensor.py 里,就把它从脉冲变成数值
(有点像 DA 转换,但多了积分)
传出来的数值已经是类比型式,所以仍然可以让远端的 relay.py 去 polling
而不是需要被 call back
因此我大概都用不到 call back.
※ 编辑: HuangJC (49.217.130.232 台湾), 01/26/2023 20:37:55
5F:推 lycantrope: mmap 01/27 21:48
6F:推 TakiDog: SharedMemory(mmap) 你的例子只是差了一个lock 01/28 04:50
7F:→ TakiDog: multiprocessing 先去看完 01/28 04:50
谢谢,我的确想过用 share memory 做
那麽这和 redis 的差别是什麽?要理解成竞争软体吗?
毕竟一个东西从来不限制只有一家公司能做
竞争的话,就是看谁便宜,看谁效能好的差别了
(我当然知道指令长得不一样,但在决策上我还是会觉得两者很像)
https://stackoverflow.com/questions/19477821/redis-cache-vs-using-memory-directly
https://tinyurl.com/6edh5emu
还真有人问
似乎是说,redis 可以存入硬碟,可以在下次执行时续用(因为它就是资料库)
资料库的话,跨语言也不成问题(比如 python 写入,c 读取)
当然 redis 也轻松跨电脑,毕竟它基於网路
但也因为基於网路,所以比纯 memory 略慢
因此如果我的 sensor.py 和 relay.py 在同一台电脑,就用 share memory
要跨电脑,就用 redis...
-----
小恶魔的心声:老板才给多少钱,我才不要写两套
用 redis 就对了,不管在同一台电脑或跨电脑都能用 XD
※ 编辑: HuangJC (49.216.44.32 台湾), 01/28/2023 18:58:28
8F:→ TakiDog: mp 是有跨环境的,可以详见 mp.BaseManager 01/30 01:40
9F:→ TakiDog: 不论是mp的share,还是使用redis, 当你使用Obj时必定会经 01/30 01:40
10F:→ TakiDog: 过serialization 01/30 01:41
11F:→ TakiDog: redis跨语言? 那就代表了你的serialization是一个通用 01/30 01:41
12F:→ TakiDog: 格式(JSON, etc.) 01/30 01:41
13F:→ TakiDog: 只要经过serialization其实效率已经不高了。 01/30 01:41
14F:→ TakiDog: 当然Redis处理了更多复杂的情境,你不需手动管理lock 01/30 01:42
15F:→ TakiDog: 慢是能慢到多少,使用者能不能接受? 01/30 01:42
16F:→ TakiDog: multiprocessing是内建的,没有竞争关系。 01/30 01:42
17F:→ TakiDog: 我自己专案是都用拉,各有优缺 01/30 01:45
18F:→ leolarrel: ZMQ or DBUS , 供参 01/30 10:05
感谢
ZMQ 似乎能让我不用再从 TCP/IP 手工打造 message loop
D-BUS 看不懂
> D-Bus是一个行程间通讯及远端程序呼叫机制,可以让多个不同的电脑程式(即行程)
> 在同一台电脑上同时进行通讯
既然它说远端(RPC),那怎麽不说它也能跨电脑?
远端呼叫经常是慢的,要写成非同步,最後我的脑袋会变成自己思考 message loop
这样我会有决策困难 XDDDD
※ 编辑: HuangJC (49.216.44.32 台湾), 01/31/2023 07:01:22
19F:→ leolarrel: 你对D-BUS才刚接触,会有一堆疑问跟不了解也是很正常 01/31 11:23
如果它能跨电脑呢?那我就想去修 wiki 了
前不久在讨论 RPI 晶片时,有位网友带着我读资料
他一边翻 wiki 给我,一边回忆他一路追这些晶片的沿革
然後很顺口的说:所以 wiki 上写错了
XDDD 热心的人很多,但错误也不少啦,但我们不敢马上改下去
改东西不好轻举妄动..
21F:→ leolarrel: 里面有写到支援tcp/ip 01/31 13:26
https://tinyurl.com/mtu3pvbc
有人做了这个比较
我想,dbus 能做的事太多了,对我的需求是杀鸡用牛刀
所以我才看不懂。
(其实 zmq 我也是一行都没用过,算不上会;但我就是能看懂一些特徵
会觉得我如果要用它,就能学会,会很好用)
就像在实作 message queue 前我只是像 mqtt 一样丢资料,收资料
但有时发送端会一口气丢一堆,接收端收一个,做一件事,才回报一件事做好了
因此才产生 message queue 的需求
懂了需求才会懂为何要有 queue,不然一开始我也不想做出 queue
※ 编辑: HuangJC (49.217.70.24 台湾), 01/31/2023 18:34:01