@ajonが指摘しているように、インデントを除いて、コードに根本的な問題はないと思います。インデントを修正すると、うまくいきます。ただし、改善の機会がいくつかあります。
1) Pythonでは、物事を反復処理する標準的な方法は、for
ループを使用することです。ループを使用する場合、for
繰り返し処理するためにループカウンター変数を定義し、それらを自分で追跡する必要はありません。代わりに、あなたはこのようなものを書きます
for line in lines:
print line
文字列のリスト内のすべての項目を繰り返し処理して印刷します。
2)ほとんどの場合、これはfor
ループがどのように見えるかです。ただし、実際にループ数を追跡したい場合があります。あなたのケースはそのような状況です。なぜなら、その1行だけでなく、次の3行も必要であり、したがって、インデックス付けにカウンターを使用する必要があるからです(lst[i]
)。そのために、があります。これenumerate()
は、アイテムのリストとそのインデックスを返し、ループすることができます。
for i, line in enumerate(lines):
print i
print line
print lines[i+7]
例のようにループカウンターを手動で追跡する場合は、次の2つがあります。
3)それはとブロックi = i+1
から移動する必要があります。どちらの場合も実行しているので、の後に配置します。あなたの場合、ブロックはそれ以上何もしません、そして排除することができます:if
else
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
ブロックを離れると、ファイルは自動的に閉じられるため、ファイルを閉じるのを忘れてしまうことはありません。
あなたの場合、2つのファイルを開いています。これは、2つの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では、2つのコンテキストマネージャーを1つの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()
3つすべてを処理できますが、行末にある行末が保持されるため、比較は失敗します。これは、を使用して解決されます。これにより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が指摘したように、このコードはすべて、検索文字列が一致する場合、それに続く行が少なくとも2行あることを前提としています。その仮定に頼ることができない場合try...except
は、@poorsodが提案するようなブロックを使用してそのケースに対処するのが正しい方法です。