Python 从 readlines() 读取前四行

1 投票
4 回答
1157 浏览
提问于 2025-04-17 12:06

我想知道怎么从 readlines() 里读取前四行,因为我从代理那里获取了 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()

4 个回答

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

if语句里面使用with是比较好的做法。如果要处理的行数很多,这样做可以避免文件处理器打开太久。使用break是因为每一行只会匹配一个模式,如果一行已经匹配了某个模式,就没必要再去检查其他模式了。

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()

如果需要做更复杂的检查,你还可以使用正则表达式。

5

使用 with 可以确保日志的良好关闭。你可以像处理任何文件一样处理 sys.stdin,这样做更快,因为它不需要创建一个列表。

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

集合是无序的,但我们可以假设行会按顺序到来,因此记录也会按顺序进行。

这种设置可能在需要更复杂的行检查时(例如使用正则表达式)会很有用。不过在你的情况下,第一个例子简洁明了,应该能很好地工作。

撰写回答