目前我正在使用子进程从catalina日志文件中读取数据:
text = subprocess.popen(" cat filename.txt",shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
文本格式将包含以下格式的行组:
INFO timestamp | Inbound Message
ID: 1234
Address: http://www.google.com
我想做的是:
for line in text.stdout.readlines():
if line.split()[line.count(' ')-2] == "Inbound":
time = "%s %s"%(line.split()[1],re.sub(',','.',line.split()[2]))
id = text.stdout.readline().split()[1]
address = text.stdout.readline().split[1]
但是,此功能似乎不起作用,因为readline()不会拉动文本中的下一行。
答案 0 :(得分:2)
你的问题是你已经调用了readlines()
,读取了所有的stdout,直到最后进入一个大的列表来循环它。因此,当您再次致电stdout.readline()
时,它不会返回任何内容,因为您已经阅读了所有内容。
这里的答案是不使用readlines()
并直接迭代文件:*
for line in text.stdout:
现在,每次循环时,text.stdout
的文件指针都指向当前行后面,因此text.stdout.readline()
将为您提供下一行(并使用它,因此它在下一次循环中不会出现。)
在这里使用next(text.stdout)
可能更具可读性,因为这样可以更清楚地使用与for
循环相同的迭代器,但它会以同样的方式产生相同的效果
话虽这么说,尝试从一个循环中消耗迭代器也是一个非常好的方法来混淆自己。您可能需要考虑退回一个级别并询问是否有更清晰的方法来解决此问题。
*事实上,"不要使用readlines()
"对于涉及readlines()
的任何代码来说,几乎总是答案,或者至少是一个有用的改进。
答案 1 :(得分:1)
不要使用子进程来获取文件的内容使用open
然后迭代文件对象上的下一个调用的文件对象,以获得包含Inbound
的行之后的两行: / p>
with open("filename.txt") as f:
for line in f:
if "| Inbound" in line:
time = line.split()[1] # split Inbound line
id = next(f).split()[1] # split following line with id
address = next(f).split()[1] # split next line containing address
print(time,id,address)
('timestamp', '1234', 'http://www.google.com')
答案 2 :(得分:1)
with open('filename.txt') as lines:
for line in lines:
if line.endswith(' | Inbound Message\n'):
timestamp = line.split()[1]
ident = next(lines).split()[1]
address = next(lines).split()[1]
print timestamp, ident, address