python读取多文件搜索关键字,速度优化问题

python读取多文件搜索关键字,速度优化问题

现在的方式是传统的 with open file:

readlines 然后 每行用__contains__(关键字)

大约20多个关键字,搜索10w个文件,需要的时间是17分钟。

佬们有没有优化的方式,意见建议都行哈

主要耗费时间是IO上,你看是否能把文件融合,达到减少IO的效果,如果不能减少数量的话,总体速度还是不够快
如果不能减少数量,建议减少文件存储方式
1.存储数据库
2.使用其他格式,例如:假如是数组,改用为npy文件存储,速度会快很多
3.如果是频繁读取,例如CS模式,可以将采取数据服务器一直将文件内容存在内存,就避免了IO操作

其次,匹配关键字用的是啥函数?可以试试map,应该也会提速

望采纳~

1、将数据分批次读取
这时候我们可以 分批次(分块)读取,而不是一次性读取 这么大体量的数据。操作步骤:

分批次读取

处理每一批次

保存每一批次的结果

对所有的数据重复步骤1-3

将所有的批次结果都结合起来

2 如果数据量太大了,还是不建议采用一些大数据技术。比如采用flink框架进行读取

这样会高效很多。
可以看一下我的博客专栏
https://blog.csdn.net/qq_15604349/category_11734572.html
望采纳!

先写个程序计算一下是哪个方面耗时比较高,一般情况是IO,建议从优化IO方面入手。

不知道你的文件大小是多小。
如果10w个文件都是小文件,而且你的内存够用,完全可以使用多进程分文件读取然后汇总结果。

可以试试多线程。如果目标文件每次都是一样的,那可以把上次匹配的文件找到,重点搜索这些

判断 word in line 的时候,把line用空格分开编程set类型,再判断,python针对in判断,对set有特别的优化,经测试,我的文本文件917kb,20个关键词,如果line是字符串判断耗时138秒,把字符串用空格分开,编程set集合,程序时间为39秒,这会大大缩短你得判断时间,另外,再用线程并发,我相信时间能够大大的缩短,


import time

start = time.time()
keyword = {
    "from","html","file","you","version","plus","is",'fb55','ms','nan',
    "native","com","http","mini","simple","abcd","map","user","admin","fast"
    
    }
with open("Ths.txt", 'r',encoding='utf8') as r:
    for i in r:
        k = set(i.split(" "))
        for word in keyword:
            if word in k:
                print(word,">>>",i)
            


end = time.time()-start

print("程序耗时:",end)

程序耗时: 39.56354570388794

1 多进程
2 文件关键字去重合并
3如果多次读取,将文件加载到内存
4 将内容入库或建立索引,有了索引秒出

为什么要readlines?
直接读取整个文件,变成字符串
用字符串查找即可
不同的应用用不同的方法,
需要readlines就用readlines
你也可以把数据读入数据库
用数据库查询法

python读取多文件搜索关键字,速度优化问题

现在的方式是传统的 with open file:

readlines 然后 每行用__contains__(关键字)

大约20多个关键字,搜索10w个文件,需要的时间是17分钟。

你上面计算的确实没有错,优化的话,得从输入输出来。看能不能减少读取的数量?不可以的话,减少存储方式

使用多线程搜索,python多线程搜索框架如下所示,read中放你的搜索方法,把搜索结果放到results中即可,par_list中一个元组对应一个线程,根据自己的需要设定线程数哈


import threadpool
#多线程执行的方法
def read(pairDate,pairShift,site,flag):
#flag返回的值为1或0
#方法省略    
        return flag
#回调函数,接收的参数(请求本身,和请求工作函数执行结果        
def get_result(request,result):
    global results
    results.append(result)

results = []
# 声明可容纳五个线程的池
pool = threadpool.ThreadPool(3)
# 创建线程运行内容请求列表(线程工作函数,线程工作参数列表,回调函数)
list_var1 = [parse_date, parse_shift, 2080, ne_flag]
list_var3 = [parse_date, parse_shift, 2090, sz_flag]
list_var2 = [parse_date, parse_shift, 5060, xb_flag]
par_list = [(list_var1, None), (list_var2, None), (list_var3, None)]
re = threadpool.makeRequests(retry_read_ApsStatus, par_list, get_result)

#将每一个线程放到线程池
res = [pool.putRequest(req) for req in re]
pool.wait()
print("多线程返回结果")
print(results)
#多线程返回结果
#[1, 1, 1]

其实这种算法一般要用C++实现的,python一般很少做这种字符串多的查找
如果题主要做的话可以看看有没有python的C语言解释器嘛

多进程

【python读取文件with open_使用Python读取大文件的方法】https://minipro.baidu.com/ma/qrcode/parser?app_key=y1lpwNoOyVpW33XOPd72rzN4aUS43Y3O&launchid=efbdc034-b6d8-431f-a22a-e9a68648c50b&path=%2Fpages%2Fblog%2Findex%3FblogId%3D110042794%26_swebFromHost%3Dbaiduboxapp

我有一个包含300+ .txt文件的文件夹,总大小为15GB +。这些文件包含推文。每行都是不同的推文。我有一个清单,我想搜索这些推文。我创建了一个脚本,用于搜索列表中每个项目的每个文件的每一行。如果tweet包含关键字,那么它将把该行写入另一个文件。这是我的代码:

# Search each file for every item in keywords
print("Searching the files of " + filename + " for the appropriate keywords...")
for file in os.listdir(file_path):
    f = open(file_path + file, 'r')
    for line in f:
        for key in keywords:
            if re.search(key, line, re.IGNORECASE):
                db.write(line)

这是每行具有的格式:

{"created_at":"Wed Feb 03 06:53:42 +0000 2016","id":694775753754316801,"id_str":"694775753754316801","text":"me with Dibyabhumi Multiple College students https:\/\/t.co\/MqmDwbCDAF","source":"\u003ca href=\"http:\/\/www.facebook.com\/twitter\" rel=\"nofollow\"\u003eFacebook\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":5981342,"id_str":"5981342","name":"Lava Kafle","screen_name":"lkafle","location":"Kathmandu, Nepal","url":"http:\/\/about.me\/lavakafle","description":"@deerwalkinc 24000+ tweeps bigdata  #Team #Genomics  http:\/\/deerwalk.com #Genetic #Testing #population #health #management #BigData #Analytics #java #hadoop","protected":false,"verified":false,"followers_count":24742,"friends_count":23169,"listed_count":1481,"favourites_count":147252,"statuses_count":171880,"created_at":"Sat May 12 04:49:14 +0000 2007","utc_offset":20700,"time_zone":"Kathmandu","geo_enabled":true,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"EDECE9","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme3\/bg.gif","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme3\/bg.gif","profile_background_tile":false,"profile_link_color":"088253","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"E3E2DE","profile_text_color":"634047","profile_use_background_image":true,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/677805092859420672\/kzoS-GZ__normal.jpg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/677805092859420672\/kzoS-GZ__normal.jpg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/5981342\/1416802075","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/MqmDwbCDAF","expanded_url":"http:\/\/fb.me\/Yj1JW9bJ","display_url":"fb.me\/Yj1JW9bJ","indices":[45,68]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false,"filter_level":"low","lang":"en","timestamp_ms":"1454482422661"}

该脚本可以工作,但是需要很多时间。大约40个关键字需要2个小时以上。显然我的代码没有优化。我该怎么做才能提高速度?
ps我已经阅读了有关搜索和速度的一些相关问题,但是我怀疑脚本中的问题在于我使用的是关键字列表。我尝试了一些建议的解决方案,但无济于事。
解决方案:
1)如果您愿意依靠外部库(并且执行时间比一次性安装的时间成本更重要),则可以通过将每个文件加载到简单的Pandas DataFrame中并执行关键字来获得一定的速度搜索为向量运算。要获得匹配的推文,您可以执行以下操作:

import pandas as pd
dataframe_from_text = pd.read_csv("/path/to/file.txt")
matched_tweets_index =  dataframe_from_text.str.match("keyword_a|keyword_b")
dataframe_from_text[matched_tweets_index] # Uses the boolean search above to filter the full dataframe
# You'd then have a mini dataframe of matching tweets in `dataframe_from_text`. 
# You could loop through these to save them out to a file using the `.to_dict(orient="records")` format.

2)将您的正则表达式分组
看起来您没有在记录与之匹配的关键字。如果是这样,则可以将关键字分组为一个正则表达式查询,如下所示:

for line in f:
    keywords_combined = "|".join(keywords)
    if re.search(keywords_combined, line, re.IGNORECASE):
        db.write(line)