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

如何确保Python脚本等待shutil.move完成后再执行后续操作?

嘿,这个问题我之前也碰到过——本质是跨进程的同步时机没把握好。shutil.move虽然是同步调用,但它的行为其实分两种情况,这直接导致了你遇到的问题:

如果源目录和目标目录在同一个文件系统下,shutil.move本质是原子性的重命名操作,文件移动完成后立刻可用;但如果是跨文件系统,它会先把文件复制到目标目录,再删除源文件——这时候你的Python脚本在shutil.move返回后就写管道,但实际文件可能还在复制过程中,C程序自然找不到。

下面给你几个靠谱的解决思路:

1. 强制验证文件就绪后再写管道

不管是不是跨文件系统,都在移动完成后验证目标文件确实存在且可访问,再通知C程序。这样最稳妥:

import os
import shutil
import time

for a_file in list_of_filenames:
    src = os.path.join(src_dir, a_file)
    dest = os.path.join(dest_dir, a_file)
    shutil.move(src, dest)
    
    # 第一步:确认文件存在
    while not os.path.exists(dest):
        time.sleep(0.01)  # 短间隔重试,避免占用过多资源
    
    # 第二步:确认文件可以被读取(防止还在写缓存)
    file_ready = False
    while not file_ready:
        try:
            with open(dest, 'r'):  # 尝试打开文件,验证可访问
                file_ready = True
        except IOError:
            time.sleep(0.01)
            continue
    
    # 验证通过后再写入管道,记得flush确保内容立刻发送
    pipe.write(f"{a_file}\n")
    pipe.flush()

2. 区分文件系统优化逻辑

如果大部分场景是同文件系统移动,可以先判断源和目标是否在同一个FS,只在跨FS时做验证,提升效率:

def is_same_filesystem(dir1, dir2):
    # 通过设备ID判断是否同文件系统
    return os.stat(dir1).st_dev == os.stat(dir2).st_dev

for a_file in list_of_filenames:
    src = os.path.join(src_dir, a_file)
    dest = os.path.join(dest_dir, a_file)
    shutil.move(src, dest)
    
    # 只有跨文件系统时才做验证
    if not is_same_filesystem(src_dir, dest_dir):
        while not os.path.exists(dest):
            time.sleep(0.01)
        try:
            with open(dest, 'r'):
                pass
        except IOError:
            time.sleep(0.01)
            continue
    
    pipe.write(f"{a_file}\n")
    pipe.flush()

3. 让C程序配合做双向同步

如果有权限修改C程序的话,最好的方式是做双向确认:Python发送文件名后,等待C程序返回“文件已就绪”的信号,再继续处理下一个文件。比如:

  • Python端代码片段:
import select

for a_file in list_of_filenames:
    # 移动文件+验证逻辑...
    pipe.write(f"{a_file}\n")
    pipe.flush()
    
    # 等待C程序的确认信号,超时5秒做异常处理
    ready, _, _ = select.select([pipe], [], [], 5.0)
    if ready:
        ack = pipe.readline().strip()
        if ack != "FILE_READY":
            # 处理异常:比如重试移动或记录日志
            print(f"Warning: C program failed to confirm {a_file}")
    else:
        print(f"Timeout waiting for C program ack for {a_file}")
  • C程序端读取文件名后,检查文件存在且可访问,再向管道写入FILE_READY\n确认。

这样可以从根本上避免同步问题,适合对可靠性要求高的场景。

内容的提问来源于stack exchange,提问作者Valentin B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:09:41