python脚本需要很长时间才能运行

时间:2016-12-15 07:32:04

标签: python

我在python中编写一个脚本来解析ldap日志,然后获取每个用户的搜索/绑定次数。我正在测试我的代码文件和小文件的代码,直到大小为5-10MB,它运行快速,并在我的本地PC上1分钟内完成。然而,当我在一个价值18M的文件上运行脚本时,它有大约150000行,大约需要5分钟,我想在100M的文件大小上运行这个脚本,每次运行可能是5-6个文件,这意味着脚本有在每次运行中解析几乎600-700M的数据。但我想这需要很长时间才能运行,所以如果我的下面的代码可以在执行时间方面进行微调以获得更好的性能,那么我需要你们的一些建议。

await

4 个答案:

答案 0 :(得分:1)

您正在对行上的整个文件进行多次扫描

count = re.findall('SEARCH REQ.*'+conid,fh1)

避免这种情况。这是你的主要问题。获取列表中的所有conid并再次迭代文件并列出,而内部循环应包含conid。把它带出外圈。您将对文件进行两次扫描。

此外,由于它是使用PyPy运行的普通Python,以便更快地运行。

使用FSM并花费更多RAM可以更好地做到这一点。这是一个提示,你必须自己做FSM。

编辑1:这是我看到日志文件后编写的脚本版本。如果有任何错误,请更正:

#!/usr/bin/env python

import sys
import re


def parse(filepath):
        d = {}
        regex1 = re.compile(r'(.*)?BIND\sREQ(.*)uid=(\w+)')
        regex2 = re.compile(r'(.*)?SEARCH\sREQ(.*)uid=(\w+)')
        with open(filepath, 'r') as f:
                for l in f:
                        m = re.search(regex1, l)
                        if m:
                                # print (m.group(3))
                                uid = m.group(3)
                                if uid in d:
                                        d[uid]['bind_count'] += 1
                                else:
                                        d[uid] = {}
                                        d[uid]['bind_count'] = 1
                                        d[uid]['search_count'] = 0
                        m = re.search(regex2, l)
                        if m:
                                # print (m.group(3))
                                uid = m.group(3)
                                if uid in d:
                                        d[uid]['search_count'] += 1
                                else:
                                        d[uid] = {}
                                        d[uid]['search_count'] = 1
                                        d[uid]['bind_count'] = 0

        for k in d:
                print('user id = ' + k, 'Bind count = ' + str(d[k]['bind_count']), 'Search count = ' + str(d[k]['search_count']))


def process_args():
        if sys.argv < 2:
                print('Usage: parse_ldap_log.py log_filepath')
                exit(1)



if __name__ == '__main__':
        process_args()
    parse(sys.argv[1])

感谢众神,保证FSM并不复杂。

答案 1 :(得分:0)

使用 itertools 库而不是那么多循环。

答案 2 :(得分:0)

您的脚本具有二次复杂度:对于文件中的每一行,您将再次读取以匹配日志条目。 我的建议是只读一次文件并计算所需条目的出现次数(一个匹配(“BIND REQ”))。

答案 3 :(得分:0)

我能用下面的代码解决我的问题。

import os,re,datetime
from collections import defaultdict



start_time=datetime.datetime.now()

bind_count=defaultdict(int)
search_conn=defaultdict(int)
bind_conn=defaultdict(str)
j=defaultdict(int)



fh = open("C:\\access","r")
total_searches=0
total_binds=0

for line in fh:
    reg1=re.search(r' BIND REQ .*conn=(\d+).*dn=(.*")', line)
    reg2=re.search(r' SEARCH REQ .*conn=(\d+).*', line)
    if reg1:
        total_binds+=1
        uid,con=reg1.group(2,1)
        bind_count[uid]=bind_count[uid]+1
        bind_conn[con]=uid

    if reg2:
        total_searches+=1
        skey=reg2.group(1)
        search_conn[skey] = search_conn[skey]+1


for conid in search_conn:
    if conid in bind_conn:
        new_key=bind_conn[conid]
        j[new_key]=j[new_key]+search_conn[conid]




for k,v in bind_count.items():
    print(k," = ",v)

print("*"*80)

for k,v in j.items():
    print(k,"-->",v)

fh.close()

del search_conn
del bind_conn

end_time=datetime.datetime.now()
print("Total time taken - {}".format(end_time-start_time))