库:sqlalchemy(连接数据库)+ pandas(取数据)
如下,首先建立连接池,然后定义函数完成取数据的操作。可以完成任务,但缺点是重复代码太多。
import sqlalchemy import pandas as pd # 建立数据库连接池 key = sqlalchemy.create_engine("oracle://test:123456@127.0.0.1:1521/muscle") def get_emp(key): sq = ''' select * from scott.emp ''' # 建立连接 + 执行sql + 返回数据(DataFrame) with key.connect() as con: res = pd.read_sql_query(sq, con) return res def get_some_thing_else(key): sq = ''' select * from sometable ''' # 建立连接 + 执行sql + 返回数据(DataFrame) with key.connect() as con: res = pd.read_sql_query(sq, con) return res搭配方式:装饰器(内置连接,连接数据库执行sql)+ 函数(定义和返回sql)。 好处是显而易见的,被装饰的函数实际上只用于定义sql,而取数据的过程完全通过装饰器来实现。但问题是一旦完成装饰器的定义,数据连接就确定了,这样显然不够灵活。
import sqlalchemy import pandas as pd def exe_sql(func): ''' 执行sql取数据,返回pd.DataFrame :param func: :return: ''' key = sqlalchemy.create_engine("oracle://test:123456@127.0.0.1:1521/muscle") def wrapper(): sq = func() with key.connect() as con: res = pd.read_sql_query(sq, con) return res return wrapper @exe_sql def get_emp(): sq = ''' select * from scott.emp ''' return sq @exe_sql def get_some_thing_else(): sq = ''' select * from sometable ''' return sq res1 = get_emp() res2 = get_some_thing_else()搭配方式:装饰器(数据库连接作为参数,连接数据库执行sql)+ 函数(定义和返回sql)。 类似于在不带参数的装饰器外再套一层,此时数据连接作为参数传入,在使用时可以灵活的进行数据库的切换。
key = sqlalchemy.create_engine("oracle://test:123456@127.0.0.1:1521/muscle") def exe_sql2(key): ''' 执行sql取数据,返回pd.DataFrame :param func: :return: ''' def decorator(func): def wrapper(): sq = func() with key.connect() as con: res = pd.read_sql_query(sq, con) return res return wrapper return decorator @exe_sql2(key) def get_emp(): sq = ''' select * from scott.emp ''' return sq在复杂一些的场景下,也可以使用类的方式来定义和整合获数据抽取的过程。
库:sqlalchemy(连接数据库)+ pandas(取数据)
问题和函数形式的一样,代码重复。
class GetScott(): def get_emp(self, key): sq = ''' select * from scott.emp ''' with key.connect() as con: res = pd.read_sql_query(sq, con) return res def get_some_thing_else(self, key): sq = ''' select * from sometable ''' with key.connect() as con: res = pd.read_sql_query(sq, con) return res scott = GetScott() scott.get_emp()由于实例方法会默认传入自身作为第一个参数,因此修饰的时候需要用到’*args。如下装饰器可以用来修饰实例方法。但是这样的方式无法灵活的使用实例本身的属性
def exe_sql3(func): ''' 执行sql取数据,返回pd.DataFrame :param func: :return: ''' key = sqlalchemy.create_engine("oracle://test:123456@127.0.0.1:1521/muscle") def wrapper(*args): # args[0] 等同于 self 参数 sq = func(*args) with key.connect() as con: res = pd.read_sql_query(sq, con) return res return wrapper class GetScott(): @exe_sql3 def get_emp(cls): sq = ''' select * from scott.emp ''' return sq scott = GetScott() scott.get_emp()由于实例方法通过self参数访问实例属性,那么修饰实例方法的装饰器只要获得self的引用就可以访问实例属性,因而可以将数据库连接作为实例属性进行赋值,而后通过装饰器进行调用。
def exe_sql4(key : str): ''' 修饰实例方法,通过传入属性名称调用实例属性 :param key: 实例属性名称 :return: ''' def decorator(func): # @functools.wraps(func) def wrapper(*args, **kwargs): self = args[0] # 实例本身 skey = getattr(self, key) sq = func(*args, **kwargs) with skey.connect() as con: res = pd.read_sql_query(sq, con) return res return wrapper return decorator class GetScott(): def __init__(self, key) -> None: self.key = key @exe_sql4('key') # 传入需要使用的属性的名称 def get_emp(cls): sq = ''' select * from scott.emp ''' return sq con = sqlalchemy.create_engine("oracle://test:123456@127.0.0.1:1521/muscle") scott = GetScott(con) scott.get_emp()通过pandas可以实现批量取数据,但是无法通过执行update等sql语句直接变更数据表,此类操作只能通过sqlalchemy实现。