欢迎来到天天文库
浏览记录
ID:8805356
大小:25.23 KB
页数:7页
时间:2018-04-08
《python本地文件搜索整理》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、python本地文件搜索整理 (2012-12-0822:38:16)转载▼标签: python 本地文件搜索 多进程通信 数据库 杂谈分类: Programming 最近再做一个本地文件搜索的东西,一个星期每天早上八点起到晚上十点都呆在自习室,终于摸点东西出来了,可是不幸的是刚要完成的时候手机就掉了,哎~手机掉了没关系,关键是里面有我太多的过去,什么东西都不能存在电脑或者手机上啊,于是乎我决定以后将东西发在别人的服务器上,好,开始 作为本地文件搜索来说,微软自带的资源浏览器有一个版本,但
2、是那个估计是及时遍历,因此速度很慢,它也会提示建立索引或很快,因此先要找到一个存放索引的地方,首先的就是数据库,毕竟本地文件多达十几万几百万,数据库的确好管理。选择的是sqlite数据库,因为作为一个软件他需要一个轻量级的东西,如果还需要用户附带安装一个mysql服务就不靠谱了 然后就是数据库表的建立,其实来说保存文件名就行了,最初的想法是建立两个表,一个文件表,存放文件和它的父目录,然后一个目录列表,保存目录和它的父目录。才想到文件和目录其实是一个东西,根本没有必要分开,就用一个简单的文件,父
3、目录代替。够简单了。基础想法是遍历目录然后将数据存进数据库,边遍历边插数据的方法显然是不靠谱的,就单进程或者单线程来说必然运势时间过长。然后就想用多线程实现吧,用多线程遍历目录,把每个线程的任务分开,因此不存在所谓的数据共享的问题,每个线程做自己的事情,确实遍历的效果不错,60秒左右就完成遍历了。但是插入数据的速度让人无法忍受,后来查询数据库的优化,才知道原来数据库每秒可以插入几百万条数据但是每秒只能提交十几个事务,因此不要频繁提交事务是事情的关键!然后就是把所有得到的数据汇合起来了一起插入后提交,插
4、入时间降低到了90秒,整个建立索引的过程需要两分半钟左右。效果已经能忍受了。继续研究发现了profile这个神器,用来分析代码性能,发现最多的事件发生在acquire上面,线程获得锁,这说明多线程作用发挥了,然后第二站时间的竟然是split操作,我们不是将文件,父目录作为一个列表的数据结构嘛,要获得整个文件的路径要split,原来如此!果断滴更改数据结构,好好思考了一下是一个字典,父目录:子文件(可以是文件或者目录),这样就可以大大去除重复数据。果然空间复杂度降低了很多,效果也不错了。再后来就是觉得这
5、个虽然是多线程但实际上遍历和插入是串行的,但是为了获得每个线程得到的结果,单独做了一个线程类,把结果存放在线程的属性中,最后要查数据非得等所有线程结束,join之后主线程才能拿到数据,这是一个阻塞的过程没有办法,最好的想法是一些线程遍历,一些线程插入数据,这必然涉及到线程间通信的问题。 线程间通信,由于操作系统学的不够好完全没啥概念,一定要好好恶补一下。然后就是各种查资料吧,发现原来cpython存在GIL全局解释锁,无法使用多核CPU!然后就想可以用多进程代替了,也确实,python中提供了m
6、ultiprocessing包,是threading类一个良好的替代品。进程间通信,由于进程机制,子进程会复制父进程的状态就似乎pid不一样,因此很多底层的东西是一样的,像Quene之类的就可以,因此可以通过这种方式来进行子进程之间的通信,而且要让一个子进程自己结束,有很好的joinableQuene类,它的taskdone方法可以告诉队列处理完毕,然后子进程退出,因此可以建立两个队列,一个是任务队列,就是要处理的任务,一个是结果队列,存放进程处理完事件获得的结果。由于数据库插入数据是很快的,瓶颈在遍
7、历数据上面,因此建立2倍于CPU的进程进行目录的遍历,然后将结果发送给一个插入数据的子进程。这里有一个技巧,就是进程类里面获取队列消息的过程是阻塞的,就是到了执行quene.get()方法的时候,他会停下来等到队列有东西出现,因此一般是一个死循环,我们可以通过手动发送None类型的数据来通知他没有任务了,创建了n个进程就要发送n个消息让其结束,注意不是有多少个任务就有多少个none,这个任务是由几个进程同时维护的,一个进程完了就会自动处理没有完成的任务,任务数比进程少的时候会收到none消息终止。然后
8、难点就是处理结果的进程何时结束,事实上是,遍历的进程完成任务将结果放到结果队列里面的时候,他就可以将后事了了然后kill了,关键是如何知道哪些进程已经结束了,我们可以选择在遍历目录的进程结束的时候发送一个none消息到结果队列,然后这个处理结果的队列知道是有多少个人给他分任务的(创建的时候传参数进来),然后每次它获得一个none消息,那个数就减一,到0的时候完成最后一个任务就可taskdone了。花了一个晚上终于实现了多进程的版本,结果所有时间合在一起就
此文档下载收益归作者所有