我写了一个小python程序作为个人实用程序来帮助我进行一些重构。它类似于unix替换,除了它支持正则表达式并对目录中的所有文件和(可选)所有子目录进行操作。
问题是我没有替换到位。我正在打开文件,将内容传递到内存中,然后覆盖文件,如下所示:
file = open('path/to/file','r')
in_string = file.read()
file.close()
# ...
#Processing logic
# ...
file = open('path/to/file','w')
file.write(out_string)
file.close()
除了显而易见的性能/内存问题,这是合法的,但对我的使用不是一个问题,这个方法还有另一个缺点。 SVN吓坏了。事后我可以做一些复制和粘贴解决方法来修复svn在提交时抛出的校验和错误,但它使得实用程序毫无意义。
有更好的方法吗?我猜测如果我正在编辑文件就不存在任何问题。我该怎么做?
答案 0 :(得分:8)
我怀疑问题是你实际上编辑了错误的文件。当您只是修改跟踪文件时,Subversion不应该引发任何关于校验和的错误 - 与 修改它们的方式无关。
也许您不小心编辑了.svn
目录中的文件?在.svn/text-base
中,Subversion使用相同的名称和扩展名.svn-base
存储文件的副本,请确保您没有编辑这些副本!
答案 1 :(得分:2)
“SVN吓坏了”是什么意思?
无论如何,vi / emacs / etc的工作方式如下:
f = open("/path/to/.file.tmp", "w")
f.write(out_string)
f.close()
os.rename("/path/to/.file.tmp", "/path/to/file")
(好吧,那里实际上有一个“fsync”......但是我不知道如何在Python中做到这一点)
它执行该复制的原因是为了确保,如果系统在写入新文件的一半时间死亡,旧的文件仍然存在...并且'重命名'操作被定义为原子,因此它将要么工作(你获得新文件的100%)或不工作(你得到100%的旧文件) - 你永远不会留下半文件。
答案 2 :(得分:1)
也许fileinput
模块可以使您的代码更简单/更短:
以下是一个例子:
import fileinput
for line in fileinput.input("test.txt", inplace=1):
print "%d: %s" % (fileinput.filelineno(), line),
答案 3 :(得分:0)
吓坏了怎么样?您所描述的内容,如果它正在运行, “就地”编辑文件,至少与 vi(1)一样。
答案 4 :(得分:0)
尝试'file = open('path / to / file','w +')'。这意味着您正在更新现有文件,而不是编写新文件。
答案 5 :(得分:0)
我怀疑Ferdinand's answer,你正在递归.svn目录,解释你为什么要搞乱SVN,但请注意你处理文件的方式还有另一个缺陷。
如果您的程序被终止,或者您的计算机在错误的位置崩溃(当您写出更改的内容时),则可能会丢失文件的原始内容和新内容。更强大的方法是执行以下步骤:
这样,如果在错误的位置被杀,您将不会有丢失数据的风险。请注意,fileinput模块将为您处理大部分内容。可以给出一系列要处理的文件,如果指定inplace = True,则会将stdout重定向到相应的文件(保留备份)。然后,您可以将代码构造为:
import os
import fileinput
def allfiles(dir, ignore_dirs=set(['.svn'])):
"""Generator yielding all writable filenames below dir.
Ignores directories specified
"""
for basedir, dirs, files in os.walk(dir):
if basedir in ignore_dirs:
dirs[:]=[] # Don't recurse
continue # Skip this directory
for filename in files:
filename = os.path.join(basedir, filename)
# Check the file is writable
if os.access(filename, os.W_OK):
yield filename
for line in fileinput.input(allfiles(PATH_TO_PROCESS), inplace=True):
line = perform_some_substitution(line)
print line.rstrip("\n") # Print adds a newline, but line already has one