您可以编写一个函数来重命名打开的文件。基本上,您关闭,重命名并重新打开该文件,保留属性(如文件位置和模式)。对于重新打开模式需要进行一些调整 - 如果文件的模式为“w”,以相同模式重新打开模式将会丢失所有内容,因此我们在重新打开时使用“r +”模式。 (这并不完美,因为它允许读取文件,这是它以前没有的,但它是我们能做的最好的。)当然,你会得到一个全新的file
对象,它是函数的返回值。
import os
def rename_open_file(fileobj, newname):
name = fileobj.name
mode = fileobj.mode.lower()
posn = fileobj.tell()
fileobj.close()
os.rename(name, newname)
newmode = mode
if "w" in mode: # can't reopen with "w" mode since
newmode = "r+" # it would empty the file; use "r+"
if "b" in mode:
newmode += "b"
fileobj = open(name, newmode)
fileobj.seek(posn)
return fileobj
f = rename_open_file(f, f.name + ".bak")
如果你有一个以上的file
对象引用打开的文件,这是没有什么帮助,当然,;所有其他参考可能会中断。
注意:该文件的name
属性不一定是完整路径,所以如果您使用相对路径打开文件,并且在打开文件后更改了目录,则这不起作用。如果这是一个问题,您可以编写自己的open()
,该文件在开放时间计算出文件的完整路径名(使用os.path.abspath()
)。
此外,打开文件时给出的缓冲区大小不会被保留,因为这不会被记录在文件对象上的任何位置。编写你自己的open()
也可以解决这个问题。最简单的方法是将子类file
。
from os.path import abspath
class open(file):
def __init__(self, filename, mode="r", buffering=-1):
file.__init__(self, abspath(filename), mode, buffering)
self.buffering = buffering
那么你可以添加保持缓冲到你的函数:
import os
def rename_open_file(fileobj, newname):
name = fileobj.name
mode = fileobj.mode.lower()
posn = fileobj.tell()
buff = fileobj.buffering
fileobj.close()
os.rename(name, newname)
newmode = mode
if "w" in mode: # can't reopen with "w" mode since
newmode = "r+" # it would empty the file; use "r+"
if "b" in mode:
newmode += "b"
fileobj = open(name, newmode, buff)
fileobj.seek(posn)
return fileobj
你也可以写一个包装类文件对象,而不是继承file
,并将它通过所有file
的方法调用包装的对象。然后rename()
可以是一个包装的方法,并做所有上述。由于调用代码将保持对包装器的引用,因此它不需要知道底层的file
对象是不同的。我将把这作为一个练习。 :-)
为什么你先打开它然后重命名它? – Jacob
'f = open('foo.txt','rw')'在我的系统上产生了一个'ValueError' - 可能你的意思是'r +'?这真的是你正在运行的代码吗? – multipleinterfaces
这与os.rename无关。你需要模式'r +' –