2011-11-12 265 views
33

是否有可能强制重命名os.rename覆盖另一个文件,如果它已经存在?例如,在下面的代码中,如果文件Tests.csv已经存在,它将被Tests.txt文件(也被重命名为Tests.csv)替换。Os.Rename中的强制覆盖

os.rename("C:\Users\Test.txt","C:\Users\Tests.csv"); 
+0

首先取消链接目标文件,捕获潜在的异常? –

+2

请记住总是在字符串中跳出反斜杠(例如使用''C:\\ Users \\ Test.txt“') – 6502

+1

...或使用'r”C:\ Users \ Test.txt“',但要小心'R “C:\\”'。 –

回答

24

你可以尝试shutil.move()

from shutil import move 

move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 

或者os.remove然后shutil.move

from os import remove 
from shutil import move 

remove('C:\\Users\\Tests.csv') 
move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 
+0

@JohnZwinck:不行,这个在Windows上运行,而'os.rename'不行。参见['shutil.move'源代码](http://hg.python.org/cpython/file/9b26fa7f9adf/Lib/shutil.py#l298)。 –

+1

那么,对于当前的答案,从我+1,但我怀疑这可能会导致竞争条件。从其他答案中我可以看出,这在Windows中是不可避免的。 –

+0

问题问“...如果存在...”,所以删除应该用if包裹或尝试逻辑 – denfromufa

0

标准库中的文件,“在Windows上,如果DST已经存在,OSERROR会即使它是一个文件也会升起;有可能是没有办法实现的原子重命名时,DST名现有文件“

http://docs.python.org/library/os.html#os.rename

因此,唯一的解决方案,不幸的是,将改变操作系统。 Windows只是在现有文件的顶部不允许使用rename()

7

在Unix上,如果dst存在并且是一个文件,如果用户有权限,它将被静默替换。如果src和dst位于不同的文件系统上,该操作可能会在某些Unix版本上失败。如果成功,重命名将是一个原子操作(这是POSIX要求)。 在Windows上,如果dst已经存在,即使它是一个文件,也会引发OSError;当dst命名现有文件时,可能无法实现原子重命名。 http://docs.python.org/library/os.html#os.rename

+6

Windows应该从地球上被驱逐的另一个原因 – MFB

+0

或者不是因为这是完全错误的,MoveFile API是原子 – paulm

2

够搞怪,为os.rename()的文件说,它取代Unix系统上的目标,但在Windows事实并非如此。他们提到了一些模糊的内容,如果目标存在于Windows上,则不可能实现原子重命名,而IMO不足以支持它。

你应该捕获OSError(目标存在于Windows上),并删除目标并重试,我想。

8

由于documentation表示如果该文件存在,就不可能保证在Windows上进行原子重命名操作,因此Python所要求的是自己执行双步os.remove + os.rename,以处理潜在的错误。

在unix系统上rename覆盖目标(如果存在)(因为操作保证是原子操作)。

请注意,即使您有权限,因为文件可能正在使用,删除目标文件也可能会失败。这是Windows文件系统的另一个重要限制,你必须在代码中自己处理它。

19

因为Python 3.3,现在有一个标准的跨平台解决方案,os.replace

重命名 文件或目录的src到DST。如果dst是一个目录,OSError将会提出 。 如果dst存在并且是一个文件,如果 用户有权限,它将被无提示替换。如果src和dst位于不同的文件系统上,操作可能会失败。如果成功,重命名将是一个原子操作(这是POSIX要求) 。

可用性:Unix,Windows。

版本3.3中的新功能。

然而,与文档相反,在Windows上它不能保证是原子的(在Python 3.4.4中)。这是因为internally它在Windows上使用MoveFileEx,这并没有做出这样的保证。

+0

MoveFileEx如何不是原子的? – paulm

+0

@paulm如果你检查它的MSDN页面,它永远不会承诺原子性,甚至明确地建议'MoveFileTransacted'作为替代。实际上,'MoveFileEx'在本地文件系统上是原子的,但在网络文件系统上是非原子的(实际上它取决于服务器)。但即使对于本地FSes而言,其原子性也是非契约性的。 – atzz