我有一个用于编辑文本文件
的python脚本
。首先,删除文本文件
的第一行
。之后,将在文本文件的末尾添加一行
。
我注意到一个奇怪的现象,但我无法解释这种行为的原因:
此脚本按预期工作(删除第一行并在文件末尾添加一行):
import fileinput
# remove first line of text file
i = 0
for line in fileinput.input('test.txt', inplace=True):
i += 1
if i != 1:
print line.strip()
# add a line at the end of the file
f = open('test.txt', 'a+') # <= line that is moved
f.write('test5')
f.close()
但是在下面的脚本中,由于在删除之前打开了文本文件
,因此会发生删除,但不会添加内容(使用write()
方法) :
import fileinput
# file opened before removing
f = open('test.txt', 'a+') # <= line that is moved
# remove first line of text file
i = 0
for line in fileinput.input('test.txt', inplace=True):
i += 1
if i != 1:
print line.strip()
# add a line at the end of the file
f.write('test5')
f.close()
请注意,在第二个示例中,open()
被放置在开头,而在第一个示例中,它是在删除文本文件
的最后一行后调用的。
该行为的解释是什么?
最佳答案
将fileinput
与inplace
参数一起使用时,修改的内容将保存在备份文件中。关闭输出文件时,备份文件将重命名为原始文件。在您的示例中,您没有显式关闭 fileinput
文件,而是依赖于自触发关闭,这没有记录并且可能不可靠。
如果我们假设再次打开同一文件会触发 fileinput.close()
,则可以最好地解释第一个示例中描述的行为。在第二个示例中,重命名仅在执行 f.close()
之后发生,从而覆盖其他更改(添加“test5”)。
因此显然您应该显式调用 fileinput.close()
以便完全控制更改何时写入磁盘。 (通常建议在不再需要外部资源时立即显式释放它们。)
编辑:
经过更深入的测试,我认为您的第二个示例中正在发生以下情况:
- 您打开一个模式为
a+
的流到文本文件,并将其绑定(bind)到变量f
。 - 您使用
fileinput
来更改同一个文件。在后台,会创建一个新文件,然后将其重命名为该文件最初的名称。注意:这实际上并没有改变原始文件 - 相反,原始文件变得无法访问,因为它以前的名称现在指向一个新文件。 - 但是,流
f
仍然指向原始文件(不再有文件名)。您仍然可以写入此文件并正确关闭它,但您无法再看到它(因为它不再有文件名)。
请注意,我不是这种低级操作的专家;细节可能是错误的,术语肯定是错误的。此外,不同操作系统和 Python 实现的行为可能有所不同。但是,它仍然可以帮助您理解为什么事情会与您的预期不同。
总之,我想说您不应该做第二个示例中所做的事情。为什么不将文件读入内存,更改它,然后将其写回磁盘呢?在 Python 中,实际就地(磁盘上)更改文件并不有趣,因为它是一种太高级的语言。
关于Python - 打开文本文件进行编辑,然后使用 fileinput.input() 对其进行修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32166062/