繁体   English   中英

覆盖外部库中的python实例方法

[英]Overriding a python instance method in a external library

我已经为数据库连接编写了上下文管理器。 我想重写外部类中的方法(在cx_oracle.Cursor中为“ execute”),以在将查询传递给数据库之前删除所有无关的绑定变量(否则它们将导致DatabaseError)。 为什么它们会从那里开始是一个正交的问题。

下面的方法有效,但是我想知道我在这里是否正确使用了_ getattribute _ (以前没有真正的借口使用过它)。

如果有人对如何从此外部库中重写此方法有更好的建议,那么我也“不知所措”。

谢谢。 我正在使用python 2.7

import cx_Oracle
from contextlib import contextmanager

class Cursor(cx_Oracle.Cursor):
    """A wrapper for cx_Oracle cursors that will drop extraneous bind variables passed to in"""

    def __init__(self, curs):
        self.curs = curs

    def execute(self, sql, *args, **kwargs):
        params = {}
        print("in execute, args[0] = [%s]" % str(args[0]))
        if len(args) == 1 and isinstance(args[0], dict):
            for bv in args[0].keys():
                if ':%s' % bv in sql:
                    params[bv] = args[0][bv]
            print('params = %s' % str(params))
        else:
            return self.curs.execute(sql, *args, **kwargs)

        return self.curs.execute(sql, params)


    def __getattribute__(self, name):
        if name == 'execute':
            return object.__getattribute__(self, name)
        elif name == 'curs':
            return object.__getattribute__(self, 'curs')
        else:
            curs = object.__getattribute__(self, 'curs')
            return cx_Oracle.Cursor.__getattribute__(curs, name)


@contextmanager
def db_conn():

    pool = cx_Oracle.SessionPool("user", "pwd", "database", min=2, max=10, increment=1, threaded=True)
    conn = pool.acquire()

    try:
        yield Cursor(conn.cursor())
    except:
        conn.rollback()
        raise
    else:
        conn.commit()
    finally:
        pool.release(conn)


if __name__ == '__main__':

    with db_conn() as curs:
        curs.execute('select * from dual where 1 = :a', {'a':1, 'b':2})
        print(curs.fetchall())

如果使用__getattr__方法而不是__getattribute__ ,则不必在自己的类中对名称进行特殊大小写。 如果无法通过常规方法找到该属性,它只会查看__getattr__

就像是:

def __getattr__(self, name):
    return getattr(self.curs, name)

您需要将class Cursor(cx_Oracle.Cursor): class Cursor(object):更改为class Cursor(object): 通过子类化来完成您想做的事情很棘手,因为游标是由数据库连接的方法创建的。 您也可以将SessionPool子类化,以便其cursor方法返回您的自定义光标实例,但这可能不值得。

暂无
暂无

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

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