繁体   English   中英

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

[英]python script taking long time to run

我在python中编写脚本a来解析ldap日志,然后获取每个用户的搜索/绑定数。 我正在示例文件和较小文件上测试我的代码,直到5-10MB大小,它可以快速运行并在本地PC上在一分钟内完成。 但是,当我在价值1800万的文件中运行脚本时,其中包含150000行,大约需要5分钟,我想以100M的文件大小运行此脚本,每次运行可能是5-6个文件,因此这意味着脚本具有每次运行可解析几乎600-700M的数据。 但是我想这将需要很长时间才能运行,因此如果可以对我的以下代码进行微调以提高执行时间的性能,我需要你们的一些建议。

import os,re,datetime
from collections import defaultdict

d=defaultdict(list)
k=defaultdict(list)
start_time=datetime.datetime.now()

fh = open("C:\\Rohit\\ECD Utilization Script - Copy\\logdir\\access","r").read()
pat=re.compile(' BIND REQ .*conn=([\d]*).*dn=(.*")')

srchStr='\n'.join(re.findall(r' SEARCH REQ .*',fh))

bindlist=re.findall(pat,fh)
for entry in bindlist:
    d[entry[-1].split(",")[0]].append(entry[0])

for key in d:
    for con in d[key]:
        count = re.findall(con,srchStr)
        k[key].append((con,len(count)))

#
for key in k:
    print("Number of searches by ",key, " : ",sum([i[1] for i in k[key]]))

for key in d:
    print("No of bind  ",key," = ",len(d[key]))


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

您正在对该行的整个文件进行几次扫描

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

避免这种情况。 这是您的主要问题。 在列表中获取所有conid,然后再次在文件上进行迭代,然后列出,而您的内部循环应由conid组成。 将其带出外部循环。 您将对文件进行两次扫描。

另外,由于它是纯Python与PyPy一起运行,因此运行速度更快。

使用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。

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

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

我可以使用以下代码解决我的问题。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM