Python datetime.strptime()占用大量的CPU时间

时间:2010-11-01 16:28:54

标签: python optimization datetime

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

目前的功能是:

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

任何人都知道如何优化这个?

4 个答案:

答案 0 :(得分:16)

如果这些是固定宽度格式,则无需解析该行 - 您可以使用切片和字典查找来直接获取字段。

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 :(得分: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

答案 2 :(得分: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()再次分开。我想知道是否有办法直接访问月份名逻辑进行一次文本转换?

答案 3 :(得分: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。