默认开启
使用默认的a(+) 选项是不可能的,如文档中所提供:
''mode 是一个可选字符串,它指定文件的模式
被打开。它默认为“r”,表示打开以阅读文本
模式。其他常用值是 'w' 用于写入(如果
它已经存在),'x' 用于创建和写入新文件,和
'a' 用于附加(在某些 Unix 系统上,意味着所有写入
不管当前的查找位置如何,都附加到文件的末尾)。''
另类
使用默认打开,这是不可能的。但是我们当然可以创建自己的文件处理程序,当文件不存在时,它将以r 和r+ 模式创建一个文件。
一个与open(filename, 'r+', *args, **kwargs) 完全一样的最小工作示例是:
import os
class FileHandler:
def __init__(self, filename, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
self.filename = filename
self.mode = mode
self.kwargs = dict(buffering=buffering, encoding=encoding, errors=errors, newline=newline, closefd=closefd)
if self.kwargs['buffering'] is None:
del self.kwargs['buffering']
def __enter__(self):
if self.mode.startswith('r') and not os.path.exists(self.filename):
with open(self.filename, 'w'): pass
self.file = open(self.filename, self.mode, **self.kwargs)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
现在当你使用以下代码时:
with FileHandler("new file.txt", "r+") as file:
file.write("First line\n")
file.write("Second line\n")
file.seek(0, 0)
file.write("Third line\n")
它会生成一个新文件new file.txt,当它不存在时,带有上下文:
Third line
Second line
如果您使用open,如果文件不存在,您将收到FileNotFoundError。
注意事项
- 我只在模式以
r 开头时创建一个新文件,所有其他文件都按正常的open 函数处理。
- 出于某种原因,将
buffering=None 直接传递给open 函数会导致TypeError: an integer is required (got type NoneType) 崩溃,因此如果它是None,我必须将其从关键字参数中删除。即使根据文档它是默认参数(如果有人知道原因,请告诉我)
编辑
以上代码没有处理以下情况:
file = FileHandler("new file.txt", "r+")
file.seek(0, 0)
file.write("Welcome")
file.close()
为了支持所有的open用例,上面的类可以使用__getattr__调整如下:
import os
class FileHandler:
def __init__(self, filename, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
self.filename = filename
self.mode = mode
self.kwargs = dict(buffering=buffering, encoding=encoding, errors=errors, newline=newline, closefd=closefd)
if self.kwargs['buffering'] is None:
del self.kwargs['buffering']
if self.mode.startswith('r') and not os.path.exists(self.filename):
with open(self.filename, 'w'): pass
self.file = open(self.filename, self.mode, **self.kwargs)
def __enter__(self):
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
def __getattr__(self, item):
if hasattr(self.file, item):
return getattr(self.file, item)
raise AttributeError(f"{type(self).__name__}, doesn't have the attribute {item!r}")