【问题标题】:shutil.copy2 - Behaviour with different file systems and pseudo filesshutil.copy2 - 不同文件系统和伪文件的行为
【发布时间】:2012-01-13 12:42:34
【问题描述】:

我写了一个小脚本来同步两个目录。该脚本允许同步某些文件类型并允许通过校验和或日期进行文件比较。 在比较之后,应该复制的文件列表被提供给使用 shutil.copy2() 模块的文件复制过程。 在各种测试运行中,我发现了 shutil.copy2 的奇怪行为,我没有解决方法:

首先: 如果源是 ext3 卷,目标是 fat32(记忆棒),shutil 会引发错误。 我认为这是因为 shutil.copy2 也尝试复制元数据,而 fat32 不支持这一点。但是我不知道如何通过 try: except: 语句来捕捉这个错误。

第二: 第二个问题更难。源和目标都是 ext3 卷。在源代码上有完整 Linux 目录树的一些备份。当我的实用程序尝试同步这些目录树时,脚本会无限循环运行,直到我的系统分区空间不足。 我尝试修复此行为并使用 stat 模块在开始复制过程之前检查源文件是否为常规文件,但这无济于事。具有奇怪行为的文件是/proc/661/fd/3。也许还有更多,但我无法测试,因为我的系统在尝试复制此文件时由于内存消耗而冻结。

我找了几天解决这两个问题的方法,希望身边的高手多多支持。

感谢您的帮助。

这里是我的文件复制过程的代码:

def _filecopy(file_list, from_dir, to_dir, overwrt):
print "Files and directories will be processed: "
for file_tupel in file_list:
    source_file_name = from_dir + file_tupel[1] + file_tupel[0]
    try:
        filemode = os.stat(source_file_name).st_mode
    except:
        filemode = 33205 
    if S_ISREG(filemode):
        target_dir_name = to_dir + file_tupel[1]
        if not os.path.isdir(target_dir_name):
            print "Create directory " + target_dir_name
            _mkdir(target_dir_name)
        target_file_name = target_dir_name + file_tupel[0]
        if os.path.isfile(target_file_name) and overwrt == "mark":
            name_appendix = "_marked_by_sync_as_different_on_" + time.strftime("%a_%d_%b_%Y_%H-%M-%S", time.localtime())
            if target_file_name.find(".") == -1:
                new_target_file_name = target_file_name + name_appendix
                new_source_file_name = source_file_name + name_appendix
            else:
                new_target_file_prefix = target_file_name.rpartition(".")[0]
                new_target_file_extension = target_file_name.rpartition(".")[2]
                new_target_file_name = new_target_file_prefix + name_appendix + "." + new_target_file_extension
                new_source_file_prefix = source_file_name.rpartition(".")[0]
                new_source_file_name = new_source_file_prefix + name_appendix + "." + new_target_file_extension
            print "Rename file " + target_file_name + " in " + new_target_file_name
            os.rename(target_file_name, new_target_file_name)
            print "Copy file " + new_target_file_name + " to " + new_source_file_name
            try:
                shutil.copy2(new_target_file_name, new_source_file_name)
            except:
                print "Could not copy " + new_target_file_name + " to " + new_source_file_name
        print "Copy file " + source_file_name + " to " + target_file_name
        try:
            shutil.copy2(source_file_name, target_file_name)
        except:
            print "Could not copy " + source_file_name + " to " + target_file_name
    else:
        print source_file_name + " seems to be no regular file and will not be copied."

按照答案 1 的提示后,shutil,copy2 语句更改为:

    shutil.copyfile(source_file_name, target_file_name)
    try:
        #try to set permission bits
        shutil.copymode(new_target_file_name, new_source_file_name)
    except:
        print "Permission bits could not be copied"
    try:
        #try to copy metadata
        shutil.copystat(new_target_file_name, new_source_file_name)
    except:
        print "Metadata could not be copied"  

【问题讨论】:

  • 请发布两个错误的完整回溯。
  • 对于 /proc 错误没有消息。系统只是冻结。
  • 文件系统错误的回溯是:文件“/home/piet/Desktop/server_disk_backup/music kopieren/pietsync.py”,第 260 行,在 _filecopy shutil.copy2(new_target_file_name, new_source_file_name) UnboundLocalError : 分配前引用的局部变量“new_target_file_name”

标签: python shutil


【解决方案1】:

shutil.copy2() 只是 shutil.copy() 后跟 shutil.copystat()。要解决您的第一个问题,您可能需要复制 source of shutil.copy2() 并将 copystat() 部分包含在 try-except 块中。您应该能够从错误回溯中找出要捕获的异常。

您可能根本不想复制/proc 文件系统。每当您调用脚本时,我都会将其排除在外。

【讨论】:

  • 我的 /proc 问题:我尽量让我的同步工具普遍可用。所以我不想按名称排除某些文件或目录。也许这个问题还有另一种解决方案。
  • 您好,感谢您的快速回复。如果我使用 shutil.copyfile() 而不是 shutil.copy() 或 shutil.copy2(),您在不同文件系统之间复制的解决方案就可以工作。但也许有更好的方法可以做到这一点,而不会为每个同步的文件引发错误。
猜你喜欢
  • 1970-01-01
  • 2012-11-14
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 2013-04-06
相关资源
最近更新 更多