2012-02-01 6 views
1

、私は私のスクリプトにプロキシからSTDINを取得しています:パイソン()

GET http://www.yum.com/ HTTP/1.1 
Host: www.yum.com 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-gb,en;q=0.5 
Accept-Encoding: gzip, deflate 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Proxy-Connection: keep-alive 

私はsys.stdin.readlines()を使用してそれを読んで、それをログに記録しますファイルが、私はGETUser-Agent行だけをファイルに記録したいと思います。

while True: 
    line = sys.stdin.readlines() 
    for l in line: 
     log = open('/tmp/redirect.log', 'a') 
     log.write(l) 
     log.close() 
+0

インデントレベルごとに4つのスペースを使用します。 –

+0

'.readlines()'を使う理由は? –

+7

なぜ読み込まれた個々の行ごとにファイルを開いたり、書き込んだり閉じたりしていますか?それはばかげているようだ。 –

答えて

5

withを使用すると、ログが良好に閉じられます。 sys.stdinは、リストを作成する必要がないため、Pythonの任意のファイルタイプのオブジェクトと同様に反復処理が可能です。

with open('/tmp/redirect.log', 'a') as log: 
    while True: #If you need to continuously check for more. 
     for line in sys.stdin: 
      if line.startswith(("GET", "User-Agent")): 
       log.write(line) 

以下は、同じ行を何度もチェックしないで、残っている行がある間だけチェックするので、効率的な方法です。おそらく状況を考えれば必要ではないかもしれませんが、あなたがチェックするアイテムが増えていれば、より多くのものを並べ替えることができます。また、あなたが持っている部品を追跡し、必要なラインを超えて読むことはできません。これは、読み取りが高価な操作である場合に有益です。

with open('/tmp/redirect.log', 'a') as log: 
    while True: #If you need to continuously check for more. 
     needed = {"GET", "User-Agent"} 
     for line in sys.stdin: 
      for item in needed: 
       if line.startswith(item): 
        log.write(line) 
        break 
      needed.remove(item) 
      if not needed: #The set is empty, we have found all the lines we need. 
       break 

セットには順序はありませんが、ラインが順番に来るので、ログに記録されると想定できます。

この種の設定は、より複雑な行のチェック(たとえば、正規表現による)の場合にも必要になる場合があります。しかし、あなたの場合、最初の例は簡潔であり、うまくいくはずです。 if文

+0

こんにちはlattyware、これは良い解決策です....しかし、私はその行の操作を行い、適切にループを壊さないように見える別の関数を持っています – krisdigitx

+1

@Lattyware 'startswith'も文字列のタプル。 – jcollado

+0

そのlattywareのおかげで.. – krisdigitx

1

あなたが取得したい4本のラインを使用して入力常にスタートと仮定すると、これは動作するはずです:

log = open('/tmp/redirect.log', 'a') 
for l in sys.stdin.readlines()[:4]: 
    log.write(l) 
log.close() 

そうでなければあなたは上の別の答えがあります(入力を解析し、おそらく正規表現を使用する必要がありますそれ)。あなたがログに書き込む前に、行の内容を確認することができます

+1

追加される各行のログを開いて閉じるのはなぜですか? –

+0

私はちょうど彼のコードをコピーしました。答えはreadlines()[:4]です - それはまったく必要ではないと私は同意します。編集。 –

3

while True: 
    lines = sys.stdin.readlines() 
    for line in lines: 
     if line.startswith('GET') or line.startswith('User-Agent:'): 
      log = open('/tmp/redirect.log', 'a') 
      log.write(l) 
      log.close() 

より複雑なチェックのために、あなたはまた、正規表現を使用することができます。

+0

は私にこのエラーを返します:if line.startswith( 'GET'): AttributeError: 'list'オブジェクトに 'startswith'という属性がありません – krisdigitx

+0

@krisdigitxこれは変数名の問題が原因でした。私はより良い名前で私の答えを更新しました。 – jcollado

+0

ありがとうございますjcollado ...私もあなたのソリューションの一部を使用して...歓声 – krisdigitx

1
>>> lines 
0: ['GET http://www.yum.com/ HTTP/1.1', 
'Host: www.yum.com', 
'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1', 
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
'Accept-Language: en-gb,en;q=0.5', 
'Accept-Encoding: gzip, deflate', 
'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7', 
'Proxy-Connection: keep-alive'] 
>>> patterns = ["GET", "User-Agent"] 
>>> for line in lines: 
...  for pattern in patterns: 
...   if line.startswith(pattern): 
...    with open("/tmp/redirect.log", "a") as f: 
...     f.write(line) 
       break 

withが内側に使用されるべきラインのリストが長い場合、これは長い時間のためにファイルハンドラの開口部につながります。すべての行が1つのパターンと一致するので、行がパターンにすでに一致している場合、リスト内の他のパタ​​ーンを確認する必要はないため、breakが使用されます。