正在编写文件时读取文件

时间:2018-02-11 04:20:34

标签: python vim operating-system

确定。这很奇怪。我从一个名为foo.txt的空文件开始,在python3解释器中编写了以下代码:

>>> import time
>>> f = open('foo.txt', 'r')
>>> while True:
...     print(f.readlines())
...     f.seek(0)
...     time.sleep(5)
... 

我开始看到这样的输出:

[]
0
[]
0

到目前为止,这么好。然后我打开另一个窗口,运行以下内容:

echo "line number 1" >> foo.txt

我的输出更改为:

['line number 1\n']
0

现在在另一个窗口中,我通过vim打开了文件并添加了一个新行,这样文件的最终状态就像这样(之后我关闭了vim)

line number 1
line number 2

奇怪的是,我仍然在翻译中看到“先前”的输出

['line number 1\n']
0
['line number 1\n']
0

我希望现在在解释器中看到两行,但事实并非如此。出于某种原因,通过echo编写文件的行为与通过vim编写文件的行为不同。

此时,我决定查看python中的文件描述符是否仍然指向原始文件。

>>> print(f.name)
foo.txt

困惑,我决定检查lsof输出

$ lsof | grep foo.txt
python3.6 .... foo.txt~
啊哈哈!最后的波浪号意味着开放的fd实际上现在指向其他东西。在ubuntu上运行相同的实验(上面是在MacOS上),lsof有一个有趣的输出

$ lsof | grep foo.txt
python3.6 .... temp.txt~ (deleted)

因此,当文件在vim中打开时,操作系统(?)在此时决定为已打开的fd创建文件的副本。 (但是当我通过echo

编辑文件时没有这样做

有谁知道为什么这只发生在vim上,而不是发生在echo?

1 个答案:

答案 0 :(得分:1)

当您在vim中保存文件(例如foo.txt)时,编辑器通常会遵循以下步骤,以避免在写入文件时出现问题时丢失内容:

  1. 在同一目录中打开一个临时名称的新文件。 (当我尝试这个时,它使用了一个四位数字作为文件名;例如,我们称之为1234。)

  2. 将缓冲区的内容写入临时文件1234

  3. 检查foo.txt上的权限和扩展属性。

  4. 删除foo.txt~(如果存在)。

  5. foo.txt重命名为foo.txt~

  6. 1234重命名为foo.txt,并将其权限和扩展属性设置为与之前的相同。

  7. 删除foo.txt~。 (如果您:set backup,则跳过此步骤。)

  8. 这意味着,当您在vim中写入文件时,原始文件将被替换为一个全新的文件。您在Python中打开的文件句柄遵循原始(现已删除)文件。

    使用>>追加到shell中的文件不会执行任何这些步骤。它只是将额外的数据写入现有文件的末尾,就像您期望的那样。