Python datetime.strptime() 消耗大量CPU时间

10 投票
4 回答
5295 浏览
提问于 2025-04-16 06:23

我有一段代码,用来解析日志,需要把时间戳转换成日期时间对象。我正在使用一个叫做datetime.strptime的函数,但根据cProfile的累积时间列,这个函数消耗了很多CPU时间。时间戳的格式是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 个回答

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

看起来在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

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展示的方式进行测试,发现这样做大约快了三倍。

撰写回答