工业AI落地,为什么90%的项目都死在“数据”上?
这两年工业AI很火。预测性维护、质量检测、能耗优化——每个方向都有公司在做。但真正落地的项目,不到10%。剩下的90%死在什么地方?死在数据上。一个真实的预测性维护项目,做了半年,失败了。客户是一个注塑厂,想用AI做注塑机的预测性维护——通过分析注塑机的压力、温度、速度曲线,预测模具什么时候会出问题。想法很好。注塑机的PLC里有完整的工艺参数——注射压力、保压压力、熔胶温度、模具温度、注射速度、保
GB28181播放自愈:NACK、降级TCP、双缓冲切换
网络抖动是视频播放最大的敌人 做安防视频项目的都知道,实验室里跑得好好的,到了客户现场就出问题。为什么?网络环境不一样。实验室是千兆交换机,客户现场可能是4G、WiFi、工业环网,丢包、抖动、带宽波动,什么都有。GB28181默认走UDP。UDP的特点是无连接、不保证顺序、不保证到达。网络一抖动,画面就花屏、卡顿、甚至断流。PyGBSentry做了三层播放自愈机制:RTCP NACK、UDP降级T
OT和IT融合,为什么90%的项目都卡在“安全”上?
最近三年,制造业数字化转型的项目里,“OT/IT融合”是被提得最多的词。IT部门想把工厂数据接入MES、ERP、云端;OT部门担心安全问题,怕生产网络被外部攻击。这个矛盾,我见过太多项目卡在这里。一个真实的项目,卡了8个月。客户是一个汽车零部件厂,IT部门想采集产线上30台设备的数据到MES系统。OT部门(设备科)坚决反对——理由是“生产网络不能跟办公网连通,万一被攻击了,整条产线停摆”。IT部门
ETF行情API接入踩坑记:从报错到跑通的七个问题
本文整理了接入ETF行情API时最常见的7个问题及解决方案,涵盖路径错误、参数格式、字段含义、WebSocket连接顺序、心跳机制、时间戳处理与多标的订阅优化。通过实际排查和代码示例,指导开发者正确调用/fund/quote接口、解析返回数据、建立稳定实时连接,并实现高效监控多只ETF,最终提供可运行的最小完整脚本。
工业数据到底该存哪里?——InfluxDB和TDengine的真实对比
一个中等规模的工厂,1000个传感器,每秒采集一次,一年产生约315亿条数据-26。用MySQL存?一张表315亿行,查询最近1小时的数据要扫描数十万行索引,响应时间从秒级到分钟级-26。写入吞吐量约2万条/秒,加上索引维护和查询并发,实际写入能力急剧下降-26。所以必须用时序数据库。但时序数据库有好几种,选哪个?我用了两年InfluxDB,后来迁到了TDengine,说一下真实感受。Influx
Python股票实时价格告警系统:WebSocket订阅与REST快照实战
本文分享了构建美股实时价格告警系统的完整过程:从初始的REST轮询因延迟高、效率低而受限,转向使用WebSocket实现低延迟订阅。重点解决了鉴权握手、心跳保活、数据字段解析(如chp涨跌幅、ts交易状态)等关键问题,并结合历史K线接口完成盘前快照分析。最终实现基于前收盘价计算涨跌幅、过滤停牌股的稳定告警系统,兼顾实时性与可靠性。
油价破百、央行决议、通胀数据扎堆:这种行情密集日该怎么盯盘
做量化这几年,我总结出一个规律:市场最容易出大行情的,不是单边趋势,而是一堆宏观事件挤在同一天的时候。最近就是这种状态。原油站上100美元,美股连跌三天,欧洲央行要公布利率决议,美国PPI和CPI数据接踵而至,比特币在8万美元门口反复试探。这种日子里,信息处理速度直接决定了你能不能抓住机会、避开风险。 这篇文章我想做两件事:一是把最近市场上最值得关注的几条主线捋清楚,说说它们之间怎么互相
(Python基础教程之二十二)爬虫下载网页视频(video blob)
现在视频链接一般为m3u8,找到m3u8地址就可以下载了打开Chrome Developer工具,然后点击“网络”标签。导航到包含视频的页面,然后开始播放。将文件列表过滤为“ m3u8”。找到master.m3u8或index.m3u8并单击它。将文件保存到磁盘并在其中查看。如果文件包含一个m3u8主URL,则复制该URL。使用ffmpeg 工具下载m3u8视频ffmpeg -i&nbs
Python 负索引与切片组合的微妙边缘情况
1. 基础回顾:负索引怎么算的Python 里负索引是从右往左数的,-1是最后一个元素,-len(lst)是第一个元素。这个大家都懂。切片语法 lst[start:stop:step]里,start 和 stop 都可以是负数。Python 的处理方式是:先把负索引转换成对应的正索引,然后再做切片。a = [0, 1, 2, 3, 4, 5]# a[-1] -> a[5] -> 5#
__reduce__ 与自定义对象序列化陷阱
好,这个问题属于那种平时不用没事,一旦要用就全是坑的典型。__reduce__这东西是 Python pickle 协议的核心钩子,但它设计的出发点跟大多数人想的完全不一样。先给你泼盆冷水:__reduce__不是为了让你方便地序列化对象,而是为了让那些没法正常 pickle 的对象能被 pickle。 这两个目标看着差不多,实际差远了。1. __reduce__到底返回什么?先看最基本的。__r
Python 在子进程中捕获信号的奇怪行为
很多人直觉上觉得,我父进程里 signal.signal(signal.SIGINT, handler)注册好了,fork出来的子进程自然也会用这个 handler。但实际跑起来你会发现各种诡异——要么信号根本没反应,要么直接默认终止了。咱们一步步拆。1. 最典型的翻车现场:subprocess.Popen启动的子进程这是最常见的坑。你用 Popen启动一个子进程,然后在父进程里给它发信号:imp
collections.ChainMap 更新操作的非直觉结果
ChainMap的写操作(增、删、改)永远只作用在它自己的 maps列表里的第一个字典上。来,我给你拆解一下这个“非直觉”到底体现在哪。1. 你以为改了“全部”,其实只改了“第一个”假设我们有这么个场景:pythonfrom collections import ChainMapdefaults = {'color': 'red', 'font':
Python 的装饰器链中返回值被覆盖的问题
这个问题其实挺经典的,尤其是在写多层装饰器的时候,经常会出现“明明加了装饰器,结果返回的东西不对了”的情况。我给你拆一下本质原因和常见的翻车现场。核心原因:装饰器的返回值替换装饰器的本质就是一个高阶函数,它接收原函数,返回一个新函数。如果你在装饰器内部没有正确地传递返回值,那原函数的返回值就会被吞掉。看这个典型的错误写法:def log_decorator(func):
Python 对 None 的特殊判断行为陷阱
这个坑属于那种你写代码时觉得“这有什么好说的”,然后线上出 bug 查半天才发现的问题。我直接给你拆几个最容易翻车的场景。核心问题:None 在条件判断中的隐式转换Python 里 None在布尔上下文中等价于 False,但这跟显式的 is None判断完全是两码事。很多人习惯写 if not x:来判空,但 x为 0、""、[]、{}的时候也会走进这个分支。def proc
asyncio.Queue 队列在取消任务时的边缘表现
这个问题其实比大多数人想的要阴险,尤其是涉及到消费者被取消时队列里还有未处理的消息这种场景。我直接给你拆几个典型边缘情况。核心问题:取消不等于消费很多人以为 task.cancel()之后,队列里的元素会自动回退或者消失。完全不是。asyncio.CancelledError是在 await点抛出的异常,如果你的消费者正在 queue.get()上阻塞,取消会直接把这个等待打断,但那个元素永远留在
Python 内置哈希函数随会话变化的陷阱
这个问题确实坑过不少人。简单说,Python内置的hash()函数在同一个程序的不同运行实例里,对同一个字符串或者自定义对象返回的值可能不一样。这不是bug,而是安全机制。根本原因Python解释器启动时会随机生成一个PYTHONHASHSEED种子值。默认情况下这个种子是随机的,导致每次运行的哈希表排列不同。这是为了防止针对字典/集合的Hash DoS攻击——如果有人能预测哈希碰撞规律,就能构造
Python 的元组拆包异常处理非直觉行为
元组拆包的异常处理有几个很“坑”的地方,特别是和其他语言的习惯不一样。第一个坑:拆包时的异常不会回滚data = [1, 2, 3]try: a, b, c, d = data # 这里ValueErrorexcept ValueError: print(f"拆包失败,但前面已经赋值了?a={a}")
contextlib.ExitStack 的异常传播边缘问题
contextlib.ExitStack的异常传播确实有些边角情况容易踩坑。先说最关键的:多个上下文管理器出错时,只有最后一个异常会抛出来,前面的异常被压制了。看看这个典型场景:pythonfrom contextlib import ExitStackdef risky_operation(): with ExitStack() as stack: &nbs
Python 中生成器表达式与闭包的组合陷阱
生成器表达式和闭包组合时有个经典的“延迟绑定”问题。直接上代码示例最容易说明:def create_multipliers(): return (lambda x: i * x for i in range(5))multipliers = list(create_multipliers())print([m(2) for m in multipliers])
Python 动态修改模块全局变量的风险
动态修改模块全局变量在工程实践中存在多种风险,主要包括以下几个方面:破坏封装性与可维护性模块的全局变量本质上是模块内部的状态,外部直接修改会破坏模块边界的完整性。后续维护时,状态变更的源头难以追踪,尤其是在多人协作或代码量较大的项目中,容易引发不可预知的副作用。线程安全问题若模块被多线程引用,直接修改全局变量可能导致数据竞争(race condition)。即使使用global关键字或setatt