我想要一个文件对象,在写入数据时直接刷新文件,并写下:
class FlushingFileObject(file):
def write(self,*args,**kwargs):
return_val= file.write(self,*args,**kwargs)
self.flush()
return return_val
def writelines(self,*args,**kwargs):
return_val= file.writelines(self,*args,**kwargs)
self.flush()
return return_val
Run Code Online (Sandbox Code Playgroud)
但有趣的是,当我写它时它没有刷新,所以我尝试了一些包括这个的东西:
class FlushingFileObject(object):
def __init__(self,*args,**kwargs):
self.file_object= file(*args,**kwargs)
def __getattr__(self, item):
return getattr(self.file_object,item)
def write(self,*args,**kwargs):
return_val= self.file_object.write(*args,**kwargs)
self.file_object.flush()
return return_val
def writelines(self,*args,**kwargs):
return_val= self.file_object.writelines(*args,**kwargs)
self.file_object.flush()
return return_val
Run Code Online (Sandbox Code Playgroud)
冲洗.
为什么不在file此实例中进行子类化工作?
好问题.
这是因为Python 通过绕过Python级方法并直接调用来优化write对file对象的write调用fputs.
要了解这一点,请考虑:
$ cat file_subclass.py
import sys
class FileSubclass(file):
def write(self, *a, **kw):
raise Exception("write called!")
writelines = write
sys.stdout = FileSubclass("/dev/null", "w")
print "foo"
sys.stderr.write("print succeeded!\n")
$ python print_magic.py
print succeeded!
Run Code Online (Sandbox Code Playgroud)
这个write方法从未被调用过!
现在,当对象不是子类时file,事情按预期工作:
$ cat object_subclass.py
import sys
class ObjectSubclass(object):
def __init__(self):
pass
def write(self, *a, **kw):
raise Exception("write called!")
writelines = write
sys.stdout = ObjectSubclass()
print "foo"
sys.stderr.write("print succeeded!\n")
$ python object_subclass.py
Traceback (most recent call last):
File "x.py", line 13, in <module>
print "foo"
File "x.py", line 8, in write
raise Exception("write called!")
Exception: write called!
Run Code Online (Sandbox Code Playgroud)
稍微深入研究Python源代码,看起来罪魁祸首是PyFile_WriteString由print语句调用的函数,该函数检查被写入的对象是否是一个实例file,如果是,则fputs直接绕过对象的方法和调用:
int
PyFile_WriteString(const char *s, PyObject *f)
{
if (f == NULL) {
/* … snip … */
}
else if (PyFile_Check(f)) { //-- `isinstance(f, file)`
PyFileObject *fobj = (PyFileObject *) f;
FILE *fp = PyFile_AsFile(f);
if (fp == NULL) {
err_closed();
return -1;
}
FILE_BEGIN_ALLOW_THREADS(fobj)
fputs(s, fp); //-- fputs, bypassing the Python object entirely
FILE_END_ALLOW_THREADS(fobj)
return 0;
}
else if (!PyErr_Occurred()) {
PyObject *v = PyString_FromString(s);
int err;
if (v == NULL)
return -1;
err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
Py_DECREF(v);
return err;
}
else
return -1;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
384 次 |
| 最近记录: |