确定。这很奇怪。我从一个名为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?
答案 0 :(得分:1)
当您在vim中保存文件(例如foo.txt
)时,编辑器通常会遵循以下步骤,以避免在写入文件时出现问题时丢失内容:
在同一目录中打开一个临时名称的新文件。 (当我尝试这个时,它使用了一个四位数字作为文件名;例如,我们称之为1234
。)
将缓冲区的内容写入临时文件1234
。
检查foo.txt
上的权限和扩展属性。
删除foo.txt~
(如果存在)。
将foo.txt
重命名为foo.txt~
。
将1234
重命名为foo.txt
,并将其权限和扩展属性设置为与之前的相同。
删除foo.txt~
。 (如果您:set backup
,则跳过此步骤。)
这意味着,当您在vim中写入文件时,原始文件将被替换为一个全新的文件。您在Python中打开的文件句柄遵循原始(现已删除)文件。
使用>>
追加到shell中的文件不会执行任何这些步骤。它只是将额外的数据写入现有文件的末尾,就像您期望的那样。