shutil.move()在Windows中对锁定文件表现奇怪

时间:2015-09-11 17:55:27

标签: python-3.x

我发现如果我尝试在已锁定的窗口中移动文件,例如在Word中打开文档,则shutil.move()将在目标文件夹中复制,然后抛出异常。我希望它只是抛出一个预期,我的应用程序不应该移动锁定的文件。

以下是代码:

for file in source_non_text_files:
    print('Unrecognized file ['+str(file)+'] moved to error folder')
    try:
        shutil.move(str(file),str(error_path))
    except IOError as err:
        print('Something went wrong'+str(err))

它可以解锁未锁定的文件。但对于锁定的文件,它会复制,然后抛出以下异常:

[WinError 32]该进程无法访问该文件,因为它正由另一个进程使用:'source_dir \ foobar.docx'

有没有办法让它按照我想要的方式在异常块中删除副本?

1 个答案:

答案 0 :(得分:0)

您似乎遇到了分享违规错误。我建议使用win32file.MoveFile函数。根据文档,它应该适当地提出一个例外,而不是创建一个副本,然后再失败。

这是我很久以前写过的一些测试用例代码,它不是你的函数的替代品,只是我编写的用于测试文件系统实现的代码(基于NTFS行为)< / p>

try:
    self.log.info("Testing that moving an open file throws a Sharing Violation)
    self.log.info("Creating file: %s" % source)
    fd = win_create.create_file(source)
    self.test_files.append(source)
    self.log.info("Attempting to move open file -- Should fail")
    try:
        win32file.MoveFile(source, target)
        self.test_files.append(target)
        raise RuntimeError("MoveFile should have failed!!")
    except win32file.error as e:
        if e.winerror is 32:  # SHARE VIOLATION
            self.log.info("Caught correct exception: %s: %s"
                          % (e.winerror, e.strerror))
            self.passed = True
        else:
            raise
except:
    self.log.error("The following exception was raised: %s"
                   % traceback.format_exc())

try: self.log.info("Testing that moving an open file throws a Sharing Violation) self.log.info("Creating file: %s" % source) fd = win_create.create_file(source) self.test_files.append(source) self.log.info("Attempting to move open file -- Should fail") try: win32file.MoveFile(source, target) self.test_files.append(target) raise RuntimeError("MoveFile should have failed!!") except win32file.error as e: if e.winerror is 32: # SHARE VIOLATION self.log.info("Caught correct exception: %s: %s" % (e.winerror, e.strerror)) self.passed = True else: raise except: self.log.error("The following exception was raised: %s" % traceback.format_exc())

否则,如果您需要跨平台兼容性,则可以使用os.rename,它也会立即引发错误。它可能需要一些os.name条件来确保您的代码在这种情况下正常运行。此外,如果您要跨文件系统进行复制,可能还需要一些额外的工作来解决跨设备错误。希望这会有所帮助。