繁体   English   中英

在 os.rename() 之后更新文件描述符

[英]update file descriptor after os.rename()

以下列方式调用os.rename()后处理Bad file descriptor错误的最佳方法是什么?

f = open('foo.txt', 'rw')
os.rename(f.name, f.name + ".bak")

在文件系统中不再有foo.txt而是foo.txt.bak

然而..

f.name

给出foo.txt而不是foo.txt.bak

但..

f.write("test")

给出Bad file descriptor

有没有更新文件描述符的好方法?

即使文件已重命名,我还应该调用f.close()吗?

您可以编写一个 function 来重命名打开的文件。 基本上,您关闭、重命名和重新打开文件,保留文件 position 和模式等属性。 重新打开需要对模式进行一些调整——如果文件的模式是“w”,以相同的模式重新打开它会丢失其中的所有内容,所以在这种情况下我们在重新打开时使用“r+”模式。 (这并不完美,因为它允许对文件进行读取访问,这是以前没有的,但这是我们能做的最好的了。)你当然会得到一个全新的file object,它是函数的返回值.

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 object 引用打开的文件,这当然无济于事; 所有其他引用可能会中断。

警告:文件的name属性不一定是完整路径,因此如果您使用相对路径打开文件并且在打开文件后更改了目录,这将不起作用。 如果这是一个问题,您可以编写自己的open()在打开时计算出文件的完整路径名(使用os.path.abspath() )。

此外,不会保留打开文件时给出的缓冲区大小,因为它没有记录在文件 object 的任何地方。 编写自己的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

然后你可以添加维护缓冲到你的 function:

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

您还可以为文件 object 编写包装器class,而不是子类化file ,并让它通过所有file的方法调用对包装的 object。 然后rename()可以是包装器的一个方法,并完成以上所有操作。 由于调用代码将保留对包装器的引用,因此它不需要知道底层file object 是不同的。 我将把它留作练习。 :-)

os.rename() 在不知道任何打开的文件对象引用该文件的情况下处理纯文件名。 因此,在对基础文件进行操作之后,您不能依赖文件 object 工作,因此关闭它可能是正确的做法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM