You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 24/7运行应用YAML文件出现NUL字符的原因求助

多实例并发写入导致YAML文件出现NUL字符的问题分析与解决

核心成因

  • 并发写入冲突:你怀疑的多实例同时操作文件是最可能的诱因。用'a'模式打开文件时,多个进程共享文件偏移指针,但yaml.dump并非原子操作——它会分批次序列化并写入数据。当两个进程同时执行写入,很可能出现进程A刚写一部分,进程B的写入打乱了文件指针,导致内核写入空字节(NUL)填充文件块,416个NUL就是这种填充的结果。
  • YAML序列化非原子性:yaml.dump处理列表时,会逐个元素序列化写入,不是一次性把整个列表写入文件。这种分段操作在并发场景下极易被打断,造成内容损坏。
  • 文件系统IO异常:如果运行环境的磁盘IO临时阻塞、缓存同步出错,也可能导致写入不完整,但结合“两周后出现”的周期,多实例并发的概率远高于这个。

验证手段

  • 排查启动日志:翻查应用的启动记录,看是否存在同一时间点重复启动的日志条目,这能直接确认多实例是否存在。
  • 模拟并发测试:写个简单脚本模拟多进程写入,大概率能复现问题。示例代码:
import yaml
import multiprocessing
import time

def concurrent_write():
    file_path = 'test_demo.yaml'
    test_data = [{'timestamp': time.time(), 'content': 'sample'}]
    for _ in range(100):
        with open(file_path, 'a') as f:
            yaml.dump(test_data, f)
        time.sleep(0.05)

if __name__ == '__main__':
    procs = [multiprocessing.Process(target=concurrent_write) for _ in range(8)]
    [p.start() for p in procs]
    [p.join() for p in procs]

运行后打开test_demo.yaml,很大概率能看到NUL字符或乱码内容。

修复方案

  • 添加文件锁:用独占锁确保同一时间只有一个进程能写入文件,可借助filelock库简化操作:
from filelock import FileLock

lock_file = f"{file_path}.lock"
with FileLock(lock_file):
    with open(file_path, 'a') as f:
        yaml.dump(summary_list, f)
  • 原子写入替换:先把内容写到临时文件,完成后再替换原文件,这个替换操作在多数文件系统是原子的,不会出现中途损坏:
import os
import tempfile

# 写入临时文件
with tempfile.NamedTemporaryFile(mode='w', delete=False, dir=os.path.dirname(file_path)) as tmp_f:
    yaml.dump(summary_list, tmp_f)
# 原子替换原文件
os.replace(tmp_f.name, file_path)
  • 防止多实例启动:应用启动时创建PID文件,检查文件是否存在且对应进程存活,避免重复启动:
import os
import psutil

pid_file = 'app.pid'
if os.path.exists(pid_file):
    with open(pid_file, 'r') as f:
        pid = int(f.read().strip())
    if psutil.pid_exists(pid):
        print("应用已在运行,退出")
        exit(1)
# 写入当前PID
with open(pid_file, 'w') as f:
    f.write(str(os.getpid()))

内容的提问来源于stack exchange,提问作者John son

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 02:15:37