Python mimetypes 的双返回值:文件是 CSV,为什么第二项还会出现 gzip 导出系统准备发送report.csv.gz,类型推断返回text/csv和gzip。若把这两项都当作媒体类型,或者看见gzip就把内容改成普通CSV发送,响应头与实际字节就会不一致。mimetypes返回的是两种元数... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python HMAC 验签的字节边界:JSON 内容没变,重新序列化后为什么仍然失败 接收一个带签名的回调,框架已经把JSON解析成字典。业务代码把字典再转回JSON,用共享密钥计算HMAC,字段和值明明一样,验签却失败。关键不在字典内容,而在发送方到底认证了哪一串字节:空格、换行和字段排列都可能改变... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python LZMA 增量解压:输入已经喂完,为什么还要继续传入空字节 为了避免解压一次产生太多内容,把max_length设为四。整份压缩字节已经送入,结果却只出现前四个字符;如果此时等下一块输入,后面的内容可能一直留在解码器内部。输入是否还需要补充与输出是否全部取走,需要读取不同状态... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python itertools.cycle:源列表已经追加元素,为什么循环里始终没有新成员 把候选列表交给cycle轮流取值,之后往原列表追加一个候选,却怎么也轮不到它。名字里的“循环”容易让人以为每轮都会重新遍历来源;实际在首次输入结束后,cycle会反复返回已经保存的元素,不会为下一圈重新获取整个来源。... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python zip_longest 的补位值:读到 None,怎样分清原值为空还是这一格根本不存在 比较两列记录时,希望较长一侧的尾部也出现在报告里,于是把zip换成zip_longest。结果里出现None,看起来像“没有数据”,但原列表本来就允许None。默认补位把原值为空与该位置不存在表示成同一个对象,报告很... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python StringIO 的覆盖写入:旧内容已放进去,为什么新文字从开头盖上去却没删掉尾巴 测试里先用StringIO装入旧报告,再write一份更短的新结果,最后得到新开头接着旧尾巴。StringIO不会因为构造时有内容就自动进入追加位置;write也不会因为从开头写入就自动删掉剩余内容。要分别安排游标移... yunqueblog/ 技术教程/ 2026-10-03/ 4 阅读
Python casefold 的位置变化:搜索命中了,为什么原文高亮却多带了一个字符 为了忽略大小写,搜索模块先把原文和查询都做casefold,再拿命中的起止位置去截原文。英文测试正常,遇到Straße!却把末尾感叹号一起高亮。原因是大小写折叠可能改变码点数量:一个原文字符在搜索文本里可以占两个位置... yunqueblog/ 技术教程/ 2026-10-03/ 2 阅读
Python LazyLoader 的触发点:只是读取模块名,为什么延后的代码已经执行了 启动流程把模块交给LazyLoader以后,调试日志只想记录module.__name__,却发现模块初始化已经完成。这个工具把加载器的执行推迟到模块属性访问;“只是看看名字”仍然属于属性访问,并不需要等到调用业务函... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python attrgetter 的点路径:同样传入 profile.name,为什么与 getattr 读到的不同 配置文件里写了一个字段选择器profile.name,交给getattr报找不到,换成attrgetter又能取到嵌套名称。两者接受相同字符串,却不执行相同的名称解释。先确定配置表达的是一个完整属性名,还是从对象开始... yunqueblog/ 技术教程/ 2026-10-03/ 3 阅读
Python QUOTE_NONNUMERIC:同一串长整数,加不加引号为什么决定能否保住末位 CSV中两个字段写着完全相同的长整数,只有第二个带双引号。启用QUOTE_NONNUMERIC读取后,前者变成浮点数且末位已改变,后者仍是完整字符串。这个参数不只控制怎样识别字段边界,还主动参与类型转换,必须与列的数... yunqueblog/ 技术教程/ 2026-10-03/ 4 阅读