Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用decorator连接到postgres数据库_Python_Postgresql - Fatal编程技术网

Python 使用decorator连接到postgres数据库

Python 使用decorator连接到postgres数据库,python,postgresql,Python,Postgresql,我正在开发一个程序,使用python和psycopg2将我的图片元数据和缩略图存储到postgres数据库中。在这个示例中,我定义了一个类MyDbase,其中包含创建表、存储值和加载值的方法。每个方法都需要连接到数据库和游标对象以执行sql命令。为了避免重复代码来建立连接并获取光标,我使用decoratorconnect创建了一个子类DbDecorators 我的问题:这是处理这个问题的正确方法吗?特别是使用with语句并将光标传递给包装器中的Dbase方法(func) from functoo

我正在开发一个程序,使用python和psycopg2将我的图片元数据和缩略图存储到postgres数据库中。在这个示例中,我定义了一个类
MyDbase
,其中包含创建表、存储值和加载值的方法。每个方法都需要连接到数据库和游标对象以执行sql命令。为了避免重复代码来建立连接并获取光标,我使用decorator
connect
创建了一个子类
DbDecorators

我的问题:这是处理这个问题的正确方法吗?特别是使用with语句并将光标传递给包装器中的Dbase方法(
func

from functools import wraps
import psycopg2


class MyDbase:
    ''' example using a decorator to connect to a dbase
    '''
    table_name = 'my_table'

    class DbDecorators:
        host = 'localhost'
        db_user = 'db_tester'
        db_user_pw = 'db_tester_pw'
        database = 'my_database'

        @classmethod
        def connect(cls, func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                connect_string = f'host=\'{cls.host}\' dbname=\'{cls.database}\''\
                                 f'user=\'{cls.db_user}\' password=\'{cls.db_user_pw}\''
                result = None
                try:
                    with psycopg2.connect(connect_string) as connection:
                        cursor = connection.cursor()
                        result = func(*args, cursor, **kwargs)

                except psycopg2.Error as error:
                    print(f'error while connect to PostgreSQL {cls.database}: '
                          f'{error}')

                finally:
                    if connection:
                        cursor.close()
                        connection.close()
                        print(f'PostgreSQL connection to {cls.database} is closed')
                return result
            return wrapper

        @staticmethod
        def get_cursor(cursor):
            if cursor:
                return cursor

            else:
                print(f'no connection to database')
                raise()


    @classmethod
    @DbDecorators.connect
    def create_table(cls, *args):
        cursor = cls.DbDecorators().get_cursor(*args)

        sql_string = f'CREATE TABLE {cls.table_name} '\
                     f'(id SERIAL PRIMARY KEY, name VARCHAR(30));'

        print(sql_string)
        cursor.execute(sql_string)

    @classmethod
    @DbDecorators.connect
    def store_value(cls, name, *args):
        cursor = cls.DbDecorators().get_cursor(*args)

        sql_string = f'INSERT INTO {cls.table_name} (name) VALUES (%s);'
        print(sql_string)
        cursor.execute(sql_string, (name,))

    @classmethod
    @DbDecorators.connect
    def load_value(cls, _id, *args):
        cursor = cls.DbDecorators().get_cursor(*args)

        sql_string = f'SELECT * FROM {cls.table_name} where id = \'{_id}\';'
        print(sql_string)
        cursor.execute(sql_string)
        db_row = cursor.fetchone()

        return db_row


def test():
    my_db = MyDbase()
    my_db.create_table()
    my_db.store_value('John Dean')
    db_row = my_db.load_value(1)
    print(f'id: {db_row[0]}, name: {db_row[1]}')

if __name__ == '__main__':
    test()

可能我没有正确地收到你的请求。为什么需要decorator而不使用上下文管理器?就像在任何文件中定义db client一样,您可以稍后从中导入它,然后在上下文管理器中使用它-

from psycopg2 import SomeDataBase  

db = SomeDataBase(credentials)

def create_table(table_name):
        with db:

            sql_string = f'CREATE TABLE {table_name} '\
                     f'(id SERIAL PRIMARY KEY, name VARCHAR(30));'

            db.cursor.execute(sql_string)

使用上下文管理器不会关闭连接,只会关闭光标。因此,在这里使用decorator模式实际上更有意义。关于上下文管理器的更多信息:(向下滚动到“with statement”部分。)

我明白你的意思。缺点是错误处理是分散的,即我需要为每个db.cursor.execute()实现一个try-except循环来捕获错误,否则程序将停止而不是记录问题。另外,我还不清楚是否需要调用db.cursor.close()。@BrunoVermeulen我已经告诉你们了错误处理的要点。使用上下文管理器cursor.close()仍将自动调用