正在寻找一种更具python风格的方式来访问数据库

正在寻找一种更具python风格的方式来访问数据库,python,mysql,Python,Mysql,我有一系列python方法遵循以下模式: def delete_session(guid): conn = get_conn() cur = conn.cursor() cur.execute("delete from sessions where guid=%s", guid) conn.commit() conn.close() 是否有一种更符合Python的方式来执行原始sql。每个方法开头和结尾的两行开始困扰我 我不是在寻找orm,我想继续使

我有一系列python方法遵循以下模式:

def delete_session(guid):
    conn = get_conn()
    cur = conn.cursor()

    cur.execute("delete from sessions where guid=%s", guid)

    conn.commit()
    conn.close()
是否有一种更符合Python的方式来执行原始sql。每个方法开头和结尾的两行开始困扰我


我不是在寻找orm,我想继续使用原始sql。

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

python文档还有一个非常符合您需要的示例。请参阅本页第8.1节,特别是开头的代码段:

db_connection = DatabaseConnection()
with db_connection as cursor:
    cursor.execute('insert into ...')
    cursor.execute('delete from ...')
    # ... more operations ...

注意执行
时,第二个参数必须是[guid](只有一个项目的列表)。至于你的问题,我通常只使用一个封装连接和游标的类,但看起来你可能更喜欢使用一个执行上下文对象,它的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法会给你一个游标,而
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;这将使您的代码

def delete_session():
    with get_cursor() as cur:
        cur.execute(etc etc)
如果您喜欢这种风格,请告诉我们,我将向您展示如何编写
get\u cursor
。毫无疑问,其他人会推荐一位装饰师,所以你可以这样写:

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

但我认为这会使提交/回滚等问题变得更为模糊。不过,如果这是您的偏好,请再次告知我们,我也可以向您展示如何编写该表单。

它不必更像Python,只需更结构化:

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))
装修工

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
“我有很多python方法遵循这种模式:”

这令人困惑

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

一系列函数

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" )
改为这样做

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" )
您的所有方法都可以看起来像delete\u session,并使用公共的
sql\u execute
方法

根据,如果您使用的是SQLite3,您甚至不需要
光标
,正如文档所说,这“通常是多余的”

相反,您可以直接在连接对象上使用快捷方式
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"

仅使用guid就可以正常工作。是否有我不知道的问题?我想我喜欢上下文管理器方法。ars提供的链接对此描述得很好,但感谢您的帮助。@Ben,cursor.execute的第二个参数必须是一个值序列(通常是元组),如果您使用的是位置参数替换(如%s或其他DB API模块?或:1),如果您使用的是命名参数替换,则必须是映射(通常是dict)(如:某些DB API模块中的guid)--不确定您使用的是什么DB API模块,但让您摆脱其他形式(例如一个独立的、非序列的、非映射的第二个参数)是非常奇怪的。我编写的一些方法将需要与结果交互。使用此方法似乎会很尴尬。在连接为c之后,您可以调用fetch方法吗失败?不,这只对一次性操作有用。