Python封装pymongo模块自动关闭连接

在我工作的项目里面使用了mongodb.自然也用到了pymongo.但是它都是在大片的函数里面使用类似于这样的方式

 代码如下 复制代码
import db
def test():
    ...
    db.test.find_one()
    ...

但是问题是在使用完都没有关闭连接,这样多台服务器连接我这台mongodb服务器,在业务高峰期就会占满我的连接, 我当时总结造成这个原因的问题有以下三种:

    上面说的用完db不关闭连接而是等着db超时

    注意上面的import,其实在import文件的时候数据库连接就已经生成了,没有在需要的时候才创建, 占满我连接的应用其实有很多没有用,浪费了

    nginx、uwsgi,celery等应用配置的问题,造成过多的实例,其实根本无益

我今天写的一个封装pymongo和关闭数据库连接的装饰器

 代码如下 复制代码
#/usr/bin/env python
# coding=utf-8

"""
1. 封装数据库操作(INSERT,FIND,UPDATE)
2. 函数执行完MONGODB操作后关闭数据库连接
"""

from functools import wraps
from pymongo.database import Database

try:
    from pymongo import MongoClient
except ImportError:
    # 好像2.4之前的pymongo都没有MongoClient,现在官网已经把Connection抛弃了
    import warnings
    warnings.warn("Strongly recommend upgrading to the latest version pymongo version,"
                  "Connection is DEPRECATED: Please use mongo_client instead.")
    from pymongo import Connection as MongoClient

class Mongo(object):

    '''封装数据库操作'''

    def __init__(self, host='localhost', port=27017, database='test',
                 max_pool_size=10, timeout=10):
        self.host = host
        self.port = port
        self.max_pool_size = max_pool_size
        self.timeout = timeout
        self.database = database

    @property
    def connect(self):
        # 我这里是为了使用类似"db.集合.操作"的操作的时候才会生成数据库连接,其实pymongo已经实现了进程池,也可以把这个db放在__init__里面,
        # 比如我把db关掉有其他的数据库调用连接又会生成,并且不影响使用.我这里只是想每次执行数据库生成一个连接用完关掉-自己控制自己的
        return MongoClientself.host, self.port, max_pool_size=self.max_pool_size,
                  connectTimeoutMS=60 * 60 * self.timeout)

    def __getitem__(self, collection):
        # 为了兼容db[集合].操作的用法
        return self.__getattr__(collection)

    def __getattr__(self, collection_or_func):
        db = self.connect[self.database]
        if collection_or_func in Database.__dict__:
            # 当调用的是db的方法就直接返回
            return getattr(db, collection_or_func)
        # 否则委派给Collection
        return Collection(db, collection_or_func)

class Collection(object):

    def __init__(self, db, collection):
        self.collection = getattr(db, collection)

    def __getattr__(self, operation):
        # 我这个封装只是为了拦截一部分操作,不符合的就直接raise属性错误
        control_type = ['disconnect', 'insert', 'update', 'find', 'find_one']
        if operation in control_type:
            return getattr(self.collection, operation)
        raise AttributeError(operation)

def close_db(dbs=['db']):
    '''
    关闭mongodb数据库连接
    db : 在执行函数里面使用的db的名字(大部分是db,也会有s_db)
        Usage::
            >>>s_db = Mongo()
            >>>@close_db(['s_db'])
            ...: def test():
            ...:     print s_db.test.insert({'a': 1, 'b': 2})
            ...:
    '''
    def _deco(func):
        @wraps(func)
        def _call(*args, **kwargs):
            result = func(*args, **kwargs)
            for db in dbs:
                try:
                    func.func_globals[db].connection.disconnect()
                except KeyError:
                    pass
            return result
        return _call
    return _deco

PS: 在我测试的时候发现,使用Mongo()类生成的db,操作完会自动关闭连接了…
怎么样给一个很大的文件每个函数都加上面的这个装饰器?

项目每个脚本的代码都很长,函数也很多,并且每个函数里面使用的db的名字都不同,比如有一些一些风格:

 代码如下 复制代码
db.test.find_one()
s_db.test.insert(dict(test='test'))
...

每个函数加一个装饰器,好费劲,就想能不能自动分辨文件中的函数然后给他们自动加装饰器,然后就有以下的一个做好的脚本:

 代码如下 复制代码
#coding=utf-8

from functools import wraps
import copy
import types

def wrap(func):
    @wraps(func)
    def _call(*args, **kwargs):
        result = func(*args, **kwargs)
        print 'wrap you'
        return result
    return _call

def test():
    print 'test'

def test2():
    print 'test3'

glocal_dict = copy.copy(globals())

func_list = [[k, v] for k, v in glocal_dict.iteritems() if not k.startswith('__')]

for func_name, func in func_list:
    if  func_name in ['wraps', 'copy', 'wrap', 'types']:
        continue
    if types.FunctionType  == type(func):
        globals()[func_name]= wrap(func)

这样当你调用的时候自动就有了装饰器:

 代码如下 复制代码
>>> from test import test
>>> test()
test
wrap you
>>>
时间: 2024-08-02 03:43:00

Python封装pymongo模块自动关闭连接的相关文章

python使用paramiko模块ssh连接远程主机,环境变量问题

问题描述 python使用paramiko模块ssh连接远程主机,环境变量问题 想写个脚本去远程维护主机,执行相应命令,但是通过python使用paramiko模块ssh连接远程主机,环境变量不跟随用户,通过export环境变量也不起作用, #!/usr/bin/python import paramiko,fileinput ssh=paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) fo

为Python安装pymssql模块来连接SQLServer

1.安装依赖包 yum install -y gcc python-devel 2.安装freetds 下载地址:http://pan.baidu.com/s/1pLKtFBl tar zxvf freetds-0.82.tar.gz cd freetds-0.82 ./configure --prefix=/usr/local/freetds --with-tdsver=8.0 --enable-msdblib --enable-dbmfix --with-gnu-ld --enable-sh

python下paramiko模块实现ssh连接登录Linux服务器

  本文实例讲述了python下paramiko模块实现ssh连接登录Linux服务器的方法.分享给大家供大家参考.具体分析如下: python下有个paramiko模块,这个模块可以实现ssh登录linux服务器,下面贴出代码,注意,我在centos5.6下,python2.6.5,paramiko-1.7的版本下测试成功. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env python import paramiko hostname='17

Python的SQLalchemy模块连接与操作MySQL的基础示例_python

一.SQLalchemy简介SQLAlchemy是一个开源的SQL工具包,基本Python编程语言的MIT许可证而发布的对象关系映射器.SQLAlchemy提供了"一个熟知的企业级全套持久性模式,使用ORM等独立SQLAlchemy的一个优势在于其允许开发人员首先考虑数据模型,并能决定稍后可视化数据的方式.二.SQLAlchempy的安装首先需安装mysql,这里就不再多说了..... 然后,下载SQLAlchemy(http://www.sqlalchemy.org/download.html

python解析xml模块封装代码_python

有如下的xml文件: 复制代码 代码如下: <?xml version="1.0" encoding="utf-8" ?>  <root>  <childs>  <child name='first' >1</child>  <child value="2">2</child>  </childs>  </root> 下面介绍python解

在Python中封装GObject模块进行图形化程序编程的教程_python

Python 是用于编码图形界面的极佳语言.由于可以迅速地编写工作代码并且不需要费时的编译周期, 所以可以立即使界面启动和运行起来,并且不久便可使用这些界面. 将这一点与 Python 易于链接本机库的能力结合起来,就可以形成一个出色的环境. gnome-python 是为 Python 封装 GNOME 及其相关库的软件包. 这使您能够用 Python 编写外观与核心 GNOME 应用程序完全相同的应用程序,而所花的时间只是用 C 编写该应用程序所花的一部分. 然而,不用 C 进行编程会有一个

Python使用SocketServer模块编写基本服务器程序的教程_python

SocketServer简化了网络服务器的编写.它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer.这4个类是同步进行处理的,另外通过ForkingMixIn和ThreadingMixIn类来支持异步. 创建服务器的步骤.首先,你必须创建一个请求处理类,它是BaseRequestHandler的子类并重载其handle()方法.其次,你必须实例化一个服务器类,传入服务器的地址和请求处理程序类.最后,调用handle_requ

Python使用poplib模块和smtplib模块收发电子邮件的教程_python

poplib模块接收邮件python的poplib模块是用来从pop3收取邮件的,也可以说它是处理邮件的第一步. POP3协议并不复杂,它也是采用的一问一答式的方式,你向服务器发送一个命令,服务器必然会回复一个信息.pop3命令码如下: 命令 poplib方法 参数 状态 描述 ----------------------------------------------------------------------------------------------- USER user user

【转载】据说是python常用的模块

difflib python diff比较模块 datetime python 处理日期与时间的模块 chardet 字符串/文件 编码检测(很好用) adodb:我们领导推荐的数据库连接组件 bsddb3:BerkeleyDB的连接组件 Cheetah-1.0:我比较喜欢这个版本的cheetah cherrypy:一个WEB framework ctypes:用来调用动态链接库 DBUtils:数据库连接池 django:一个WEB framework docutils:用来写文档的 dpkt