如果你想在文件的顶部的文本,你应该做这样的事情:
temp_fname = "temp_file"
# the next line doesn't work in Python 2.5, 2.6, or 3.0
with open(fullname, "r") as in_file, open(temp_fname, "w") as out_file:
out_file.write(appendtext)
for line in in_file:
out_file.write(line)
os.rename(temp_fname, fullname)
下面是改写为Python 2.6以上:
temp_fname = "temp_file"
with open(temp_fname, "w") as out_file:
with open(fullname, "r") as in_file:
out_file.write(appendtext)
for line in in_file:
out_file.write(line)
os.rename(temp_fname, fullname)
我们可以做得比这更好一点。这总是使用相同的临时文件名("temp_file"
),并且该文件将始终创建在单个目录(运行此目录时的默认目录)。我们真正想要的是一个临时文件,它具有唯一的名称,与我们要编辑的文件完全相同的目录中创建。 Python为我们提供了一个名为tempfile
的便利模块,它可以创建临时文件。
默认情况下,你只是得到一个打开的文件句柄,你不知道文件名。但是我们需要知道文件名,以便在临时拷贝完成后,我们可以将它重命名为原始文件名。 tempfile
为此类情况提供了NamedTemporaryFile
。
这是一个完整的程序:
import fnmatch
import os
import sys
import tempfile
headertext = "# header text\n\n"
def want_this_file(fname):
for pat in ['*']:
if fnmatch.fnmatch(fname, pat):
return True
return False
def prepend_file(fullname, path):
# with statement means temp file is written and closed at end of with
with tempfile.NamedTemporaryFile(dir=path, delete=False) as out_file:
with open(fullname, "r") as in_file:
out_file.write(headertext)
for line in in_file:
out_file.write(line)
# before temp file is closed, get its name
temp_fname = out_file.name
# rename temp file to fullname, clobbering original
os.rename(temp_fname, fullname)
start_directory = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(start_directory):
for fname in filenames:
if want_this_file(fname):
fullname = os.path.join(dirpath, fname)
prepend_file(fullname, dirpath)
这个答案使用该模式,“写一个临时文件,然后重命名临时文件原来的名称”。这是你应该这样做的方式。它允许代码编写新版本,并且只有当新版本完全成功写入时,然后才会执行一个操作,将新文件重命名为旧文件名。因此,如果在尝试写入新版本时出现任何问题,原始文件将保持不变。这是解决问题的安全方法。
我们希望在原始文件所在的目录下创建临时文件,这样os.rename()
操作将会非常便宜。在Linux系统上,您的系统临时目录(/tmp
)可能位于其自己的分区上,如果您只是让tempfile
在那里创建它的临时文件,那么重命名操作可能涉及到再次复制数据!如果临时文件位于同一目录中,则重命名操作总是非常快速且安全。
编辑:这是一个改进版本的代码。这会捕获错误,并在重新引发错误信号之前清理临时文件。同样,正如J.F.塞巴斯蒂安指出的,文件应该以二进制模式打开;这是做的。
import fnmatch
import os
import shutil
import sys
import tempfile
file_patterns_to_match = ['*']
headertext = "# header text\n\n"
# make any newlines in headertext match the system line ending
headertext = headertext.replace('\n', os.linesep)
def want_this_file(fname):
for pat in file_patterns_to_match:
if fnmatch.fnmatch(fname, pat):
return True
return False
def prepend_file(fullname, path):
# with statement means temp file is written and closed at end of with
with tempfile.NamedTemporaryFile(dir=path, delete=False) as out_file:
# get the name immediately
temp_fname = out_file.name
try:
# use binary mode to avoid newline translations
with open(fullname, "rb") as in_file:
out_file.write(headertext)
shutil.copyfileobj(in_file, out_file)
except Exception:
# on any error, clean up temp file and re-raise exception
try:
os.remove(temp_fname)
except Exception:
print("unable to clean up temp file: " + temp_fname)
pass
raise
# rename temp file to fullname, clobbering original
os.rename(temp_fname, fullname)
start_directory = sys.argv[1]
for dirpath, dirnames, filenames in os.walk(start_directory):
for fname in filenames:
if want_this_file(fname):
fullname = os.path.join(dirpath, fname)
prepend_file(fullname, dirpath)
“附加”表示“添加到结尾”。你想要的是“预先安排”。 –
@FrancisAvila - 问题是它甚至没有附加文本结束..如果它的工作,我可以尝试chagne预先 – user1934146
是否打印fnmatch.filter(文件,拍)产生任何东西? – jfs