[英]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.