为什么一个文件对象刷新,而另一个文件对象不刷新?

2024-09-24 22:31:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我想要一个文件对象,在写入数据时直接刷新到文件中,并编写了以下内容:

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

但有趣的是,当我写信给它的时候,它并没有变红,所以我尝试了一些方法,包括:

^{pr2}$

是冲的。在

为什么子类化file在这个实例中不起作用?在


Tags: 文件数据对象selfwritelinesreturndefargs
2条回答

好问题。在

这是因为Python通过绕过Python级别的write方法并直接调用fputs来优化对file对象的调用。在

要了解这一点,请考虑:

$ 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!

从未调用write方法!在

现在,当对象不是file的子类时,一切都按预期工作:

^{pr2}$

仔细研究一下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;
}

file.flush()的文档说明:

注意 flush()不一定要将文件的数据写入磁盘。使用flush()后跟操作系统同步()以确保这种行为。在

我测试了FlushingFileObject的第一个版本,没有操作系统同步打电话。文件没有刷新。插入os.fsync(self.fileno())后,文件被刷新。然后我把操作系统同步打电话现在文件被刷新了!我想可以肯定的是操作系统同步打电话是必要的。在

相关问题 更多 >