2011-04-19 50 views
2

我已經編寫了數據庫連接的上下文管理器。 我想重寫一個外部類(cx_oracle.Cursor中的'execute')的方法,在將查詢傳遞給數據庫之前刪除任何無關的綁定變量(否則它們會導致DatabaseError)。他們爲什麼會在那裏開始的問題是正交的。覆蓋外部庫中的python實例方法

下面的作品,但我不知道我是否正在使用_ 的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()) 

回答

1

如果使用__getattr__方法,而不是__getattribute__,你沒有特殊情況下的名稱在自己的類。如果它不能通過正常方式找到屬性,它只會看到__getattr__

喜歡的東西:

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

你需要改變class Cursor(cx_Oracle.Cursor):class Cursor(object):。通過子類化來做你想做的事情是很棘手的,因爲遊標是通過數據庫連接的方法創建的。您也可以繼承SessionPool的子類,以便其cursor方法返回您的自定義遊標實例,但這可能不值得您付出努力。

+0

謝謝!這看起來完全像我想要的(我需要更熟悉特殊的方法)。我開始繼承cx_Oracle.Cursor的唯一原因是自動獲得其他方法。這給了我。 – Gerrat 2011-04-19 20:58:22

+0

@Gerrat:不客氣。這裏有很多信息:http://docs.python.org/reference/datamodel.html – 2011-04-19 22:07:33