[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1
Skipping C:\temp\PP3E\Examples\PP3E\TempParts\lawnlake1-jan-03.jpg
1428 => C:\temp\PP3E\Examples\PP3E\TempParts\part-001.txt
1429 => C:\temp\PP3E\Examples\PP3E\TempParts\part-002.html
Edited 8 files, visited 1429

This, finally, is the exact tool I was looking for to simplify global book examples tree
maintenance. After major changes to things such as shared modules and file and di-
rectory names, I run this script on the examples root directory with an appropriate
search string and edit any files it pops up as needed. I still need to change files by hand
in the editor, but that’s often safer than blind global replacements.


Global Replacements in Directory Trees (Visitor)


But since I brought it up: given a general tree traversal class, it’s easy to code a global
search-and-replace subclass, too. The ReplaceVisitor class in Example 6-20 is a Search
Visitor subclass that customizes the visitfile method to globally replace any appear-
ances of one string with another, in all text files at and below a root directory. It also
collects the names of all files that were changed in a list just in case you wish to go
through and verify the automatic edits applied (a text editor could be automatically
popped up on each changed file, for instance).


Example 6-20. PP4E\Tools\visitor_replace.py


"""
Use: "python ...\Tools\visitor_replace.py rootdir fromStr toStr".
Does global search-and-replace in all files in a directory tree: replaces
fromStr with toStr in all text files; this is powerful but dangerous!!
visitor_edit.py runs an editor for you to verify and make changes, and so
is safer; use visitor_collect.py to simply collect matched files list;
listonly mode here is similar to both SearchVisitor and CollectVisitor;
"""


import sys
from visitor import SearchVisitor


class ReplaceVisitor(SearchVisitor):
"""
Change fromStr to toStr in files at and below startDir;
files changed available in obj.changed list after a run
"""
def init(self, fromStr, toStr, listOnly=False, trace=0):
self.changed = []
self.toStr = toStr
self.listOnly = listOnly
SearchVisitor.init(self, fromStr, trace)


def visitmatch(self, fname, text):
self.changed.append(fname)
if not self.listOnly:
fromStr, toStr = self.context, self.toStr
text = text.replace(fromStr, toStr)
open(fname, 'w').write(text)


336 | Chapter 6: Complete System Programs

Free download pdf