2010-11-01 54 views
7

我有一些日志解析代码需要将时间戳记转换为日期时间对象。我使用的是datetime.strptime,但是这个函数根据cPro​​file的cumtime列使用了很多cputime。时间戳的格式为01/Nov/2010:07:49:33Python datetime.strptime()吃了很多CPU时间

目前的功能是:

new_entry['time'] = datetime.strptime(
     parsed_line['day'] + 
     parsed_line['month'] + 
     parsed_line['year'] + 
     parsed_line['hour'] + 
     parsed_line['minute'] + 
     parsed_line['second'] 
     , "%d%b%Y%H%M%S" 
) 

有谁知道我可能会优化呢?

回答

13

如果这些是固定宽度格式,那么就不需要分析这一行 - 您可以使用切片和字典查找来直接获取字段。

month_abbreviations = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 
         'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 
         'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12} 
year = int(line[7:11]) 
month = month_abbreviations[line[3:6]] 
day = int(line[0:2]) 
hour = int(line[12:14]) 
minute = int(line[15:17]) 
second = int(line[18:20]) 
new_entry['time'] = datetime.datetime(year, month, day, hour, minute, second) 

测试在由Glenn Maynard所示的方式示出了该要快3倍左右。

+1

把它变成一个函数,并在我的代码中对这个和strptime()之间来回多次相同的100万条日志行进行测试。总分析时间始终在80到50秒之间! – 2010-11-02 18:40:01

+0

好的解决方案。你能否请我也建议如果我有12个小时的格式,我该怎么办?除了放置条件并手动完成之外,还有其他方法可以处理吗? – Naman 2015-04-15 05:47:02

+1

@Naman你可以添加'am_pm_offset = {'AM':0,'PM':12}'并且添加到几个小时。 – 2015-04-15 11:49:24

2

最近的答案:如果移动到直线strptime()一直没有好转的运行时间,那么我怀疑的是,其实,这儿没有问题:你只是写了一个方案,其主要目的之一生活拨打电话strptime()很多次,而且你已经写得够好了 - 只有很少的其他东西 - 它确实允许strptime()调用主导运行时。我认为你可以把这看作是成功而不是失败,除非你发现(a)一些Unicode或LANG设置正在使strptime()做额外的工作,或者(b)你比你需要的更频繁地调用它。当然,尝试在每个日期解析时只调用一次。 :-)

看到示例日期字符串后的后续答案:等等!等一下!为什么你解析线,而不是仅仅使用一个格式化字符串,如:

"%d/%b/%Y:%H:%M:%S" 

原始现成的,袖口回答:如果月份是一个整数,你可以做这样的事情:

new_entry['time'] = datetime.datetime(
    int(parsed_line['year']), 
    int(parsed_line['month']), 
    int(parsed_line['day']), 
    int(parsed_line['hour']), 
    int(parsed_line['minute']), 
    int(parsed_line['second']) 
) 

并避免创建一个大的字符串只是为了使strptime()再次拆分它。我想知道是否有办法直接访问月份名称逻辑来执行这种文本转换?

+0

试图不解析分离的日期,让strptime做到这一点,按您的编辑。在运行时间上没有太大的区别... – 2010-11-01 16:47:47

+0

使用strptime()时,你应该只是一个格式化字符串。这是预期的用途。 – 2010-11-01 16:50:20

+0

好吧,我试着把这部分作为自己的一组工作线程来加速它。我得到了结果,我敢打赌,大多数非线程主人们在尝试这种方式时得到的结果是...慢了一倍;-) – 2010-11-02 17:18:53

2

什么是“很多时间”? strptime这里需要约30微秒:

from datetime import datetime 
import timeit 
def f(): 
    datetime.strptime("01/Nov/2010:07:49:33", "%d/%b/%Y:%H:%M:%S") 
n = 100000 
print "%.6f" % (timeit.timeit(f, number=n)/n) 

打印0.000031。

+0

根据cprofile,累计为38个CPU秒。该程序的总数为154个CPU秒。 – 2010-11-01 17:57:43

+0

什么? (此评论的其余部分在这里,因为StackOverflow将其用户视为需要强制最小注释长度的子项) – 2010-11-01 18:01:11

+0

他正在解析日志文件,并且strptime正在执行总计154个执行时间中的38个。 – 2013-01-03 04:58:41

3

似乎在Windows平台上使用strptime()使用Python实现(Lib目录中的_strptime.py)。而不是C一个。自己处理字符串可能会更快。

from datetime import datetime 
import timeit 

def f(): 
    datetime.strptime ("2010-11-01", "%Y-%m-%d") 

n = 100000 
print "%.6f" % (timeit.timeit(f, number=n)/n) 

收益0.000049我的系统上,而

from datetime import date 
import timeit 

def f(): 
    parts = [int (x) for x in "2010-11-01".split ("-")] 
    return date (parts[0], parts[1], parts[2])  

n = 100000 
print "%.6f" % (timeit.timeit(f, number=n)/n) 

收益0.000009