鍍金池/ 問答/Java  Python  網(wǎng)絡(luò)安全/ pymongo不使用close方法時(shí),內(nèi)存占用很大,求解

pymongo不使用close方法時(shí),內(nèi)存占用很大,求解

爬蟲時(shí),如果不使用pymongo的close方法,python xxx.py內(nèi)存會一點(diǎn)一點(diǎn)的上漲,最開始900多M,慢慢的就1個(gè)多G,快到2G了。但是速度快,在tail -f log的時(shí)候,基本看不清輸出信息。

如果使用了close方法,內(nèi)存穩(wěn)定在500M左右,但是讀和取數(shù)據(jù)庫速度慢,在tail log的時(shí)候,能看到正在保存哪個(gè)URL,正在獲取哪個(gè)URL。

請問我該如何解決這個(gè)問題呢。

#-*-coding:utf-8-*-
import logging
import setting
import time,datetime
from setting import mongo_host,mongo_port,mongo_db_name_data,mongo_db_name_linkbase,mongo_db_name_task
import pymongo

logging.basicConfig(filename='log',level=logging.INFO)


class Connect_mongo(object):
    def __init__(self):
        self.mongo_host = mongo_host
        self.mongo_port = mongo_port
        self.conn()

    def conn(self):
        self.client = pymongo.MongoClient(host=self.mongo_host,port=self.mongo_port)
        self.db_data = self.client[mongo_db_name_data]
        self.db_linkbase = self.client[mongo_db_name_linkbase]
        self.db_linkbase_collection = self.db_linkbase.linkbase
        self.db_task = self.client[mongo_db_name_task]

    def insert_db(self,item):
        setting.my_logger.info('當(dāng)前插入數(shù)據(jù)庫的最終數(shù)據(jù)為%s'%item)
        self.db_data.xxx_data.update({"car_id":item['car_id']},item,True)
        self.client.close()

    def save_linkbase(self,response_result,spider_name,hash_url,item_type):
        if item_type == 'carinfo_item':
            linkinfo = {}
            linkinfo['status'] = response_result.status_code
            linkinfo['url'] = response_result.url
            linkinfo['spider_name'] = spider_name
            linkinfo['hash_url'] = hash_url
            #保存到linkbase
            self.db_linkbase_collection.update({"status":linkinfo['status'],"hash_url":hash_url},linkinfo,True)
            self.client.close()
        else:
            self.db_linkbase_collection.create_index([("over_time", pymongo.ASCENDING)], expireAfterSeconds=7200)
            linkinfo = {}
            linkinfo['status'] = response_result.status_code
            linkinfo['url'] = response_result.url
            linkinfo['spider_name'] = spider_name
            linkinfo['hash_url'] = hash_url
            linkinfo['over_time'] = datetime.datetime.utcnow()
            #保存到linkbase
            self.db_linkbase_collection.update({"status":linkinfo['status'],"hash_url":hash_url},linkinfo,True)
            self.client.close()

    def save_task(self,task):
        setting.my_logger.info('當(dāng)前插入數(shù)據(jù)庫的task信息為%s'%task)
        self.db_task.xxx_task.update({'url':task['url']},task,True)
        self.client.close()

    def get_task(self,max_requests=10):
        task = []
        for i in range(max_requests):
            result = self.db_task.xxx_task.find_one_and_delete({})
            task.append(result)
        return task

    def duplicate_removal(self,hash_data):
        result = self.db_linkbase.linkbase.find_one({'hash_url':hash_data})
        if result == None:
            return True
        else:
            return False


mongo_insert = Connect_mongo()

在另一個(gè)py文件中使用requests進(jìn)行爬蟲和xpath進(jìn)行處理,然后存儲或取數(shù)據(jù)庫。

回答
編輯回答
枕邊人

內(nèi)存占用跟你取出來的數(shù)據(jù)是如何緩存,以及你是否釋放了內(nèi)存有關(guān)。
舉個(gè)例子,一次性取出5萬條記錄,然后存在一個(gè)list中,如果取多了,不停往list中添加,內(nèi)存占用自然就大了,因?yàn)楸旧韮?nèi)存中存的數(shù)據(jù)就這么大,你都要用到,這是沒辦法解決的問題。除非你擴(kuò)內(nèi)存條。
而如果是另一種情況,你每次都實(shí)例化一個(gè)MongoClient,查詢出來的task沒有刪掉,就會導(dǎo)致無用的result還緩存著數(shù)據(jù),沒有被回收,導(dǎo)致內(nèi)存成倍增長。此時(shí),只要在你不用這些數(shù)據(jù)的時(shí)候del task一下就OK了。
你如何使用的,如何導(dǎo)致內(nèi)存增長的得自己看。

2017年9月1日 12:03
編輯回答
不將就

連接資源一定要及時(shí)釋放(不然長時(shí)間運(yùn)行會出大問題的比如可能會出現(xiàn)大量的closed_wait連接), 思考的方向是如何避免頻繁的建立連接,使用連接池會是個(gè)不錯(cuò)的選擇,pymongo 應(yīng)該是有連接池的支持的

2017年3月27日 09:10