正如@ajon 所指出的,我认为您的代码除了缩进之外没有任何根本性的问题。缩进固定后,它对我有用。然而,有几个改进的机会。
1)在 Python 中,迭代事物的标准方法是使用for
循环。使用for
循环时,您无需定义循环计数器变量并自己跟踪它们以迭代事物。相反,你写这样的东西
for line in lines:
print line
遍历字符串列表中的所有项目并打印它们。
2)在大多数情况下,这就是您的for
循环的样子。但是,在某些情况下,您确实确实想要跟踪循环计数。你的情况就是这样的情况,因为你不仅需要那一行,还需要接下来的三行,因此需要使用计数器进行索引(lst[i]
)。为此,enumerate()
它将返回一个项目列表及其索引,然后您可以在其上循环。
for i, line in enumerate(lines):
print i
print line
print lines[i+7]
如果您要像示例中那样手动跟踪循环计数器,则有两件事:
3)那i = i+1
应该移出if
andelse
块。你在这两种情况下都这样做,所以把它放在if/else
. 在您的情况下,该else
块不再做任何事情,并且可以被消除:
while i < 500:
if Lines[i] == searchquery:
f2.write(Lines[i])
f2.write(Lines[i+1])
f2.write(Lines[i+2])
i = i+1
4)现在,这将导致IndexError
文件少于 500 行。您应该使用正在迭代的序列的实际长度,而不是硬编码 500 的循环计数。len(lines)
会给你那个长度。但是不要使用while
循环,而是使用for
循环并range(len(lst))
遍历从零到len(lst) - 1
.
for i in range(len(lst)):
print lst[i]
5) open()
可以用作上下文管理器,负责为您关闭文件。上下文管理器是一个相当高级的概念,但如果已经为您提供了它们,则使用起来非常简单。通过做这样的事情
with open('test.txt') as f:
f.write('foo')
f
该文件将在该with
块内打开并可供您访问。离开区块后,文件将自动关闭,因此您不会忘记关闭文件。
在您的情况下,您正在打开两个文件。这可以通过使用两个with
语句并嵌套它们来完成
with open('one.txt') as f1:
with open('two.txt') as f2:
f1.write('foo')
f2.write('bar')
或者,在 Python 2.7 / Python 3.x 中,通过在单个with
语句中嵌套两个上下文管理器:
with open('one.txt') as f1, open('two.txt', 'a') as f2:
f1.write('foo')
f2.write('bar')
6)根据创建文件的操作系统,行尾不同。在类 UNIX 平台上,它是\n
.OS X 之前的 Mac \r
,Windows 使用\r\n
. 所以这Lines[i] == searchquery
与 Mac 或 Windows 行结尾不匹配。file.readline()
可以处理所有这三个,但是因为它保留了行尾的任何行尾,所以比较将失败。这可以通过 using 解决str.strip()
,它将去除开头和结尾的所有空白字符串,并比较没有行结尾的搜索模式:
searchquery = 'am'
# ...
if line.strip() == searchquery:
# ...
file.read()
(使用和使用读取文件str.splitlines()
将是另一种选择。)
但是,由于您提到您的搜索字符串实际上出现在该行的开头,让我们这样做,使用str.startswith()
:
if line.startswith(searchquery):
# ...
7) Python 的官方风格指南PEP8建议CamelCase
用于类,lowercase_underscore
几乎所有其他东西(变量、函数、属性、方法、模块、包)。所以而不是Lines
使用lines
. 与其他方面相比,这绝对是一个小问题,但仍然值得尽早做好。
因此,考虑到所有这些事情,我会这样编写您的代码:
searchquery = 'am'
with open('Test.txt') as f1:
with open('Output.txt', 'a') as f2:
lines = f1.readlines()
for i, line in enumerate(lines):
if line.startswith(searchquery):
f2.write(line)
f2.write(lines[i + 1])
f2.write(lines[i + 2])
正如@TomK 指出的那样,所有这些代码都假定如果您的搜索字符串匹配,那么它后面至少有两行。如果你不能依赖这个假设,那么使用try...except
@poorsod 建议的块来处理这种情况是正确的方法。