Iterating over multiple files and replacing a single line - why doesn't it work?
I'm trying to use the fileinput
module to iterate over a bunch of files and replace a single line in them. This is how my code looks:
def main():
for root, dirs, files in os.walk('target/generated-sources'):
for line in fileinput.input([os.path.join(root, file) for file in files if file.endsWith('.java')], inplace=True):
match = re.search(r'@Table\(name = "(.*)"\)', line)
output = "".join(['@Table(name = "', PREFIX, match.group(1)[MAX_TABLENAME_LEN - len(PREFIX)], '")', '\n']) if match e开发者_如何学编程lse line
print output,
The problem I face is that I get no error, and the script somehow seems to block. I'm using Python 2.5.2.
Your list comprehension is returning empty lists when a root does not contain .java
files. When your script passes an empty list to fileinput.input()
, it reverts to the default expecting input from stdin. Since there is nothing coming in from stdin, your script blocks.
Try this instead:
def main():
for root, dirs, files in os.walk('target/generated-sources'):
java_files = [os.path.join(root, file) for file in files if file.endsWith('.java')]
if not java_files: # go to next iteration if list is empty
continue
for line in fileinput.input(java_files, inplace=True):
match = re.search(r'@Table\(name = "(.*)"\)', line)
output = "".join(['@Table(name = "', PREFIX, match.group(1)[MAX_TABLENAME_LEN - len(PREFIX)], '")', '\n']) if match else line
print output,
Alternatively, split up the logic of the file discovery. The following creates a generator which produces a list of files which you can then use as an input to fileinput
.
import os, fnmatch, fileinput
def find_files(directory, pattern):
"Generator that returns files within direction with name matching pattern"
for root, dirs, files in os.walk(directory):
for basename in fnmatch.filter(files, pattern):
filename = os.path.join(root, basename)
yield filename
for line in fileinput.input(find_files("target/generated-sources", "*.java")):
match = re.search(r'@Table\(name = "(.*)"\)', line)
output = "".join(['@Table(name = "', PREFIX, match.group(1)[MAX_TABLENAME_LEN - len(PREFIX)], '")', '\n']) if match else line
print output,
If you want to know where the interpreter blocks, you can send signal SIGINT to the process. At least on unix like operating systems.
kill -sigint PID
Try to add some print or logging- lines, to see where your code hangs. Maybe fileinput works well, and the app blocks after that.
Some time ago I wrote a tool to do search+replace in several files: http://www.thomas-guettler.de/scripts/reprec.py.txt
精彩评论