简体   繁体   English

在 python 中第二次读取文件时出现问题

[英]Issues while reading a file for second time in python

I am a bit confused as to why the following code snippet returns the correct output while reading the same file for second time:我有点困惑为什么以下代码片段在第二次读取同一个文件时返回正确的 output :

textCont = "Hello World"
print("Original content of the file")
print(open(filename).read())
textFile = open(filename, "w")
textFile.write(textCont)
print("New file content:")
textFile = open(filename)
print(textFile.read())
textFile.close()

where filename is a file that contains some existing data.其中filename是包含一些现有数据的文件。 This file is to be read, over-written and then read again.该文件将被读取、覆盖然后再次读取。

In the above case, the same variable has been used for opening the file in write mode, and then in read mode.在上述情况下,相同的变量已用于以写入模式打开文件,然后以读取模式打开文件。 This works fine and gives a proper output when it is read for the second time (showing the content which has overwritten the previous one)这工作正常,并在第二次读取时给出正确的 output(显示已覆盖前一个的内容)

But the following version of the code doesn't work:但是以下版本的代码不起作用:

textCont = "Hello World"
print("Original content of the file")
print(open(filename).read())
textFile = open(filename, "w")
textFile.write(textCont)
print("New file content:")
textFile_1 = open(filename)
print(textFile_1.read())
textFile.close()
textFile_1.close()

When read is done for the second time using variable other than the one used for opening the file in write mode, then it returns an empty string.当第二次使用变量而不是用于以写入模式打开文件的变量完成读取时,它返回一个空字符串。

I know the fact that when the same file is read for second time, it returns an empty string.我知道当第二次读取同一个文件时,它返回一个空字符串。 But then why the code in the first case returns the correct output?但是为什么第一种情况下的代码会返回正确的 output?

Can anyone please provide a suitable explanation of this?谁能提供一个合适的解释?

The issue in the second case got resolved, thanks to @Stefan.多亏了@Stefan,第二种情况的问题得到了解决。

The solution is to close the file just after writing but before reading it again.解决方案是在写入后但再次读取之前关闭文件。

print(open(filename).read())
textFile = open(filename, "w")
textFile.write(textCont)
textFile.close() // close the file from write mode before reading it again
print("your file content:")
textFile_1 = open(filename)
print(textFile_1.read())
textFile_1.close()

The first thing to understand is that when you do textFile.write there is no certainty that the write to the file will happen immediately.首先要了解的是,当您执行 textFile.write 时,无法确定写入文件会立即发生。 This is to make the writing more efficient by putting the data first in a buffer which will be written to the file only when it is full or flush is called or the file is closed (which internally does a flush).这是通过将数据首先放在缓冲区中来提高写入效率,该缓冲区仅在文件已满或调用刷新或文件关闭(内部执行刷新)时才会写入文件。

(Technically, flush is not enough to ensure that the data is written to the file see os.fsync ) (从技术上讲,flush 不足以确保将数据写入文件,请参见os.fsync

So the reason is does not work with two different variables name is because the write operation never really happens before the line textFile_1.close()所以原因是不适用于两个不同的变量名称是因为写操作在textFile_1.close()行之前从未真正发生过

The reason it "works" with the same variable name is that when you rebind textFile = open(filename) the file that was previously bound to textFile is now not referenced anywhere and thus the garbage collector deletes it.它使用相同变量名“工作”的原因是,当您重新绑定textFile = open(filename)时,以前绑定到textFile的文件现在没有在任何地方引用,因此垃圾收集器将其删除。 When a file handle is deleted the data is written to the file and thus you can read it afterward.当文件句柄被删除时,数据被写入文件,因此您可以在之后读取它。

Also, you should use the with open idiom when dealing with files: link此外,您应该在处理文件时使用 with open 习惯用法: link

See below, the FileDebug wrapper shows you when the file is being deleted and thus when the data is written.见下文,FileDebug 包装器会向您显示文件何时被删除以及数据何时被写入。

class FileDebug:
    def __init__(self, f, name):
        self.f = f
        self.name = name

    def close(self):
        print(f"Closing file (var: {self.name})")
        self.f.close()

    def write(self, *args, **kwargs):
        self.f.write(*args, **kwargs)

    def read(self, *args, **kwargs):
        return self.f.read(*args, **kwargs)

    def __del__(self):
        print(f"Del completed (var: {self.name})")

filename = "text.txt"
def different_name():
    textCont = "Hello World"
    print("Original content of the file")
    print(FileDebug(open(filename), "No name").read())
    textFile = FileDebug(open(filename, "w"), "textFile")
    textFile.write(textCont)
    print("New file content:")
    textFile_1 = FileDebug(open(filename), "textFile_1")
    print(textFile_1.read())
    textFile.close()
    textFile_1.close()

def same_name():
    textCont = "Hello World"
    print("Original content of the file")
    print(FileDebug(open(filename), "No name").read())
    textFile = FileDebug(open(filename, "w"), "textFile")
    textFile.write(textCont)
    print("New file content:")
    textFile = FileDebug(open(filename), "textFile")
    print(textFile.read())
    textFile.close()


different_name()
"""
Original content of the file
Del completed (var: No name)

New file content:

Closing file (var: textFile)
Closing file (var: textFile_1)
Del completed (var: textFile)
Del completed (var: textFile_1)
"""

#same_name()
"""
Original content of the file
Del completed (var: No name)

New file content:
Del completed (var: textFile) # the file is closed and the data is written
Hello World
Closing file (var: textFile)
Del completed (var: textFile)
"""

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM