代码之家  ›  专栏  ›  技术社区  ›  Ben Noland

正在寻找访问数据库的一种更为蟒蛇式的方法

  •  4
  • Ben Noland  · 技术社区  · 15 年前

    我有很多遵循这种模式的Python方法:

    def delete_session(guid):
        conn = get_conn()
        cur = conn.cursor()
    
        cur.execute("delete from sessions where guid=%s", guid)
    
        conn.commit()
        conn.close()
    

    有没有一种更像蟒蛇般的方法来执行原始SQL?每种方法开头和结尾的两行开始困扰着我。

    我不想找ORM,我想坚持使用原始SQL。

    6 回复  |  直到 8 年前
        1
  •  8
  •   twasbrillig    10 年前

    您可以编写一个上下文管理器并使用WITH语句。例如,请参阅以下博客文章:

    http://jessenoller.com/2009/02/03/get-with-the-program-as-contextmanager-completely-different/

    另外,python文档还有一个与您的需求非常匹配的示例。请参见本页第8.1节,尤其是以下代码段:

    db_connection = DatabaseConnection()
    with db_connection as cursor:
        cursor.execute('insert into ...')
        cursor.execute('delete from ...')
        # ... more operations ...
    
        2
  •  3
  •   Alex Martelli    15 年前

    小心点。 execute 第二个参数必须是[guid](只有一个项目的列表)。对于您的问题,我通常只使用一个类封装连接和光标,但看起来您可能更喜欢使用 执行上下文 对象的对象 __enter__ 方法给您一个光标,而 __leave__ 提交或回滚取决于终止是正常的还是异常的;这将使您的代码

    def delete_session():
        with get_cursor() as cur:
            cur.execute(etc etc)
    

    如果你喜欢这种风格,请告诉我们,我会教你怎么写 get_cursor . 其他人无疑会推荐一个装饰师,所以你会写:

    @withcursor
    def delete_session(cur):
        cur.execute(etc etc)
    

    但我认为这使得提交/回滚等问题变得更加模糊。但是,如果 是你的喜好,再次让我们知道,我也可以教你如何写那张表格。

        3
  •  3
  •   S.Lott    15 年前

    “我有许多遵循此模式的Python方法:

    这让人困惑。

    要么你有一堆函数,要么你有一堆类的方法。

    一堆函数 .

    改为这样做。

    class SQLFunction( object ):
        def __init__( self, connection ):
            self.connection = connection
        def __call__( self, args=None ):
            self.cursor= self.connection.cursor()
            self.run( args )
            self.cursor.commit()
            self.cursor.close()
    
    class DeleteSession( SQLFunction ):
        def run( self, args ):
            self.cursor.execute( "statement" )
    
    delete_session = DeleteSession( connection )
    

    函数声明有两行长,但本质上是相同的。 你可以做到 func1( args ) 因为它是一个可调用的对象。其余的 你的程序应该保持不变。

    一个类中的一组方法 .

    class SomeClass( object ):
        def __init__( self, connection ):
            self.connection= connection
        def sql_execute( self, statement, args= None )
            self.cursor= self.connection.cursor() 
            self.cursor.execute( statement, args if args is not None else [] )
            self.connection.commit()
            self.cursor.close()
        def delete_session( self ):
            self.sql_execute( "statement" )
    

    您的所有方法都可以像删除会话一样使用 sql_execute 方法。

        4
  •  0
  •   paxdiablo    15 年前

    它不需要更多的蟒蛇,只需要更结构化:

    def execSql(statement):
        conn = get_conn()
        cur = conn.cursor()
        cur.execute(statement)
        conn.commit()
        conn.close()
    
    def delete_session(guid):
        execSql("delete from sessions where guid=%s"%(guid))
    
        5
  •  0
  •   eduffy    15 年前

    装饰师?

    class SqlExec:
       def __init__ (self, f):
          self.f = f
       def __call__ (self, *args):
          conn = get_conn() 
          cur = conn.cursor()
          cur.execute(self.f (*args))
          conn.commit()
          conn.close()
    
    @SqlExec
    def delete_session(guid):
          return "delete from sessions where guid=%s" % guid
    
        6
  •  0
  •   LondonRob    8 年前

    根据 docs ,如果使用sqlite3,甚至 需要 Cursor 正如医生所说,这是“常常是多余的”。

    相反,您可以使用快捷方式 execute executemany executescript 直接在连接对象上:

    import sqlite3
    
    persons = [
        ("Hugo", "Boss"),
        ("Calvin", "Klein")
        ]
    
    con = sqlite3.connect(":memory:")
    
    # Create the table
    con.execute("create table person(firstname, lastname)")
    
    # Fill the table
    con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)
    
    # Print the table contents
    for row in con.execute("select firstname, lastname from person"):
        print row
    
    print "I just deleted", con.execute("delete from person").rowcount, "rows"