在Python中从用户输入逐行交互式编辑文件
我想知道如何在Python中逐行编辑一个文件。
比如说,我有一个文本文件,里面通常是这样的:
key value
key value
key value
key value
key value
...
每一行的内容不一定是相同的配对。这只是我解释的方式。
我想在终端上逐行显示键和值,然后我想做以下两件事之一:
- 只需按回车键(或者其他快捷键)继续读取(显示)下一行。
- 输入一个新值,然后按回车。这实际上会替换文件中显示的值,最后继续显示下一对键值。
一直到文件结束,或者直到我输入'quit'或其他关键词也可以,没关系。
- 能够返回到上一行会是个加分项(以防不小心跳到下一行),但现在不是特别重要。
我发现自己经常以一种非常乏味和重复的方式编辑大型文件,文本编辑器在按箭头键时光标到处乱跑,真的很让人沮丧。而且使用退格键删除也很烦人。
我知道如何在Python中读取文件和写入文件,但不知道如何以这种互动的方式来做。我只知道如何一次性写入整个文件。此外,我也不知道同时以读取和写入的方式打开同一个文件是否安全。我知道如何处理每一行,如何将文本拆分成值的列表等等……我真正需要的是理解如何在当前这一行修改文件,并且妥善处理这种交互。
那么,最好的方法是什么呢?
2 个回答
我会这样做:先把文本文件里的所有行都加载到一个列表里,然后逐行查看这个列表,边看边修改里面的内容。最后,当你到达最后一行或者想要的时候,就把这个完整的列表写回到同样名字的文件里,这样就会覆盖掉旧的文件。
所有的回答都集中在把文件内容加载到内存中,修改后再保存到磁盘上,所以我想试试另一种方法:
import os
sep = " "
with open("inline-t.txt", "rb+") as fd:
seekpos = fd.tell()
line = fd.readline()
while line:
print line
next = raw_input(">>> ")
if next == ":q":
break
if next:
values = line.split(sep)
newval = values[0] + sep + next + '\n'
if len(newval) == len(line):
fd.seek(seekpos)
fd.write(newval)
fd.flush()
os.fsync(fd)
else:
remaining = fd.read()
fd.seek(seekpos)
fd.write(newval + remaining)
fd.flush()
os.fsync(fd)
fd.seek(seekpos)
line = fd.readline()
seekpos = fd.tell()
line = fd.readline()
这个脚本简单地打开文件,一行一行地读取,如果用户输入了新值,就会重写这一行。如果新数据的长度和原来的数据一样,那么只需要找到原来的位置写入就可以了。如果新数据的大小不一样,我们就需要清理一下。这样的话,就要把文件剩下的内容读取出来,和新数据拼接在一起,然后全部重新写回磁盘。使用fd.flush和os.fsync(fd)可以确保更改在写入后立刻在文件中生效。这可能不是性能最好的解决方案,但我觉得这更接近他所要求的。
另外,考虑到这段代码可能有一些小问题,我相信还有优化的空间——比如可以在开始时进行一次全局读取,以避免频繁读取整个文件,特别是当需要调整的更改比较多的时候,或者类似的做法。