python中的文件编辑
我写了一个小python程序作为个人工具来帮助我进行一些重构。它与unix replace类似,只是它支持正则表达式,并对目录和(可选)所有子目录中的所有文件进行操作 问题是我没有替换到位。我打开文件,将内容传递到内存,然后覆盖文件,如下所示:python中的文件编辑,python,svn,Python,Svn,我写了一个小python程序作为个人工具来帮助我进行一些重构。它与unix replace类似,只是它支持正则表达式,并对目录和(可选)所有子目录中的所有文件进行操作 问题是我没有替换到位。我打开文件,将内容传递到内存,然后覆盖文件,如下所示: file = open('path/to/file','r') in_string = file.read() file.close() # ... #Processing logic # ... file = open('path/to/file','
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在提交时抛出的校验和错误,但这会使实用程序变得毫无意义
有更好的方法吗?我猜,如果我在原地编辑文件,就不会有任何问题。我该怎么做呢?我该怎么做?你所描述的,如果它工作的话,就是“就地”编辑文件,至少和vi(1)一样多。尝试“file=open('path/to/file','w+')”。这意味着您正在更新现有文件,而不是编写新文件。我怀疑问题在于您实际上编辑了错误的文件。当您只是修改跟踪文件时,Subversion不应该在校验和方面产生任何错误——不管您是如何修改它们的 可能是您无意中编辑了
.svn
目录中的文件?在.svn/text base
中,Subversion使用相同的名称和扩展名.svn base
存储文件副本,请确保您没有编辑这些文件 你说的“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%)——永远不会留下半个文件。也许
文件输入
模块可以使代码更简单/更短:
下面是一个例子:
import fileinput
for line in fileinput.input("test.txt", inplace=1):
print "%d: %s" % (fileinput.filelineno(), line),
我猜想,您正在递归到.svn目录中,这解释了为什么会弄乱svn,但请注意,在处理文件的方式中还有另一个缺陷
如果您的程序被终止,或者您的计算机在错误的点(当您写出更改的内容时)崩溃,则可能会丢失文件的原始内容和新内容。更稳健的方法是执行以下步骤:
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
这几乎肯定是问题所在。我在SVN WC中递归使用sed有过这样的经验。如果OP决定接受这个答案(或类似的答案),也许问题的标题应该重新命名,以便将来的人员搜索可能会发现它与这个问题有关?还要注意,OP的工具应该尊重只读标志。.svn中的文件是只读的。fileinput还有其他用途。。。但这不是最好的使用方法<代码>用于文件中的行(“test.txt”):打印“行:”,行更好。谢谢!我最终实现了类似的东西,但是使用了用于ignore_dirs的正则表达式。walk()列出相对于原始调用路径的所有BaseDir,这意味着所有文件('.')都不会跳过'/.svn'或'/.subdir/.svn'。现在很高兴了解fileinput!