[英]Is there a faster way to parse this text file?
我正在从一些类似于此的文本文件中解析日期/时间/测量信息:
[Sun Jul 15 09:05:56.724 2018] *000129.32347
[Sun Jul 15 09:05:57.722 2018] *000129.32352
[Sun Jul 15 09:05:58.721 2018] *000129.32342
[Sun Jul 15 09:05:59.719 2018] *000129.32338
[Sun Jul 15 09:06:00.733 2018] *000129.32338
[Sun Jul 15 09:06:01.732 2018] *000129.32352
结果进入这样的输出文件:
07-15-2018 09:05:56.724, 29.32347
07-15-2018 09:05:57.722, 29.32352
07-15-2018 09:05:58.721, 29.32342
07-15-2018 09:05:59.719, 29.32338
07-15-2018 09:06:00.733, 29.32338
07-15-2018 09:06:01.732, 29.32352
我正在使用的代码如下所示:
import os
import datetime
with open('dq_barorun_20180715_calibtest.log', 'r') as fh, open('output.txt' , 'w') as fh2:
for line in fh:
line = line.split()
monthalpha = line[1]
month = datetime.datetime.strptime(monthalpha, '%b').strftime('%m')
day = line[2]
time = line[3]
yearbracket = line[4]
year = yearbracket[0:4]
pressfull = line[5]
press = pressfull[5:13]
timestamp = month+"-"+day+"-"+year+" "+time
fh2.write(timestamp + ", " + press + "\n")
这段代码运行良好并完成了我的需要,但我正在尝试学习更有效的 Python 文件解析方法。 处理一个 100MB 的文件大约需要 30 秒,我有几个大小为 1-2GB 的文件。 有没有更快的方法解析这个文件?
您可以声明months
dict 不使用datetime
模块,这应该会快一点。
months = {"Jan": "01", "Feb": "02", "Mar": "03", "Apr": "04", "May": "05", "Jun": "06",
"Jul": "07", "Aug": "08", "Sep": "09", "Oct": "10", "Nov": "11", "Dec": "12"}
您也可以使用解包使您的代码更简单:
for line in fh:
_, month, day, time, year, last = line.split()
res = months[month] + "-" + day + "-" + year[:4] + " " + time + ", " + last[5:]
fh2.write(res)
PS timeit
显示它大约快 10 倍
您应该使用 Pandas DataFrames 来快速加载和操作大数据:
import pandas as pd, datetime
df = pd.read_csv('dq_barorun_20180715_calibtest.log',header=None,sep=' ')
df[0] = df.apply(lambda x: x[0][1:],axis=1)
df[1] = df.apply(lambda x: datetime.datetime.strptime(x[1], '%b').strftime('%m'), axis=1)
df[4] = df.apply(lambda x: x[4][:-1],axis=1)
df[5] = df.apply(lambda x: ' ' + x[5][5:],axis=1)
df['timestamp'] = df.apply(lambda x: x[1]+"-"+str(x[2])+"-"+x[4]+" "+x[3], axis = 1)
df.to_csv('output.txt',columns=['timestamp',5],header=False, index=False)
由于您有固定的职位和从月份名称到数字的简单转换,这应该有效
#! /usr/bin/env python3
m = {'Jan':'01', 'Feb':'02', 'Mar':'03', 'Apr':'04', 'May':'05', 'Jun':'06', 'Jul':'07', 'Aug':'08', 'Sep':'09', 'Oct':'10', 'Nov':'11', 'Dec':'12'}
with open('dq_barorun_20180715_calibtest.log', 'r') as fh, open('output.txt' , 'w') as fh2:
for line in fh:
day = line[9:11]
month = m[line[5:8]]
year = line[25:29]
time = line[12:24]
val = line[36:44]
print('{}-{}-{} {}, {}'.format(month, day, year, time, val), file=fh2)
这是使用 Pandas read_csv 的另一种方法,如果你有很多大文件,你可以使用dask
它也支持这个。
import pandas as pd
import datetime
df = pd.read_csv('D:\\test.txt',sep='\*0001')
df.columns = ['dates','val']
df.dates = pd.to_datetime(df.dates.str[1:-2])
df.to_csv("output.csv",header=None,index=None)
然后,您可以使用不同的方法将日期转换为您想要的格式。
我可能有一个完全不同的想法,但它并没有加快解析速度。
如果这不是您想要的,因为您要求更快的解析,请发表评论,我将删除此答案。
您应该将大型输入文件拆分为较小的段。 例如,您可以尝试获取行数并将其除以合适的数字。 假设有 40,000 行,那么您可以将其分成 4 段,每段接近 10,000 行。 记下起始索引以及要处理的行数。 (请注意,最后一个偏移量可能小于 10,000。 )
然后将输入文件传递给多个线程,这些线程只读取从start-index
到输入文件offset
的给定部分并解析这部分。 各个线程将解析的部分写入共享文件夹中,但使用索引文件名。 每个线程完成后,您可以将共享文件夹中的所有文件合并为一个output.txt
。
以下是一些有关如何实现其中一些目标的链接资源:
为避免打开文件过大,导致内存占用过多,本代码使用Python yield技术,使用常规内容。 具体的实际性能,可以和自己写的代码进行性能对比。
以下代码已在本地运行!
import datetime
import re
# File path to be cleaned
CONTENT_PATH = './test03.txt'
# File path of cleaning results
RESULT_PATH = './test03.log'
def read(file):
with open(file) as obj:
while True:
line = obj.readline()
if line:
yield line
else:
return
def tsplit(line):
_m, _d, _y = line[5:8], line[9:11], line[25:29]
_m = datetime.datetime.strptime(_m, '%b').strftime('%m')
rt = "%s-%s-%s" % (_m, _d, _y)
return rt
hour_min_sen = re.compile(r'(\d{2}:\d{2}:\d{2}.\d{2})')
end = re.compile(r'(\d{2}\.\d{5})')
with open(RESULT_PATH, 'a+') as obj:
for line in read(CONTENT_PATH):
line = line.strip()
"""
[Sun Jul 15 09:06:01.732 2018] *000129.32352
"""
group = hour_min_sen.findall(line)
end_group = end.findall(line)
"""
07-15-2018 09:05:56.724, 29.32347
"""
obj.write("%s %s, %s\n" % (tsplit(line), group[0], end_group[0]))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.