簡體   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