в поисках более питонного способа доступа к базе данных - PullRequest
4 голосов
/ 10 июля 2009

У меня есть несколько методов python, которые следуют этой схеме:

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

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

    conn.commit()
    conn.close()

Есть ли более питонный способ выполнить raw sql. 2 строки в начале и конце каждого метода начинают беспокоить меня.

Я не ищу orm, я хочу придерживаться raw sql.

Ответы [ 6 ]

8 голосов
/ 10 июля 2009

Вы можете написать менеджер контекста и использовать оператор 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 ...
3 голосов
/ 10 июля 2009

"У меня есть несколько методов 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" )

Все ваши методы могут выглядеть как delete_session и использовать обычный sql_execute метод.

3 голосов
/ 10 июля 2009

Осторожно, 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)

но я думаю, что это делает коммит / откат, среди прочего, немного мрачнее. Тем не менее, если этот является вашим предпочтением, снова дайте нам знать, и я также могу показать вам, как написать эту форму.

0 голосов
/ 29 сентября 2016

Согласно документам , если бы вы использовали SQLite3, вам бы даже не потребовалось a 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"
0 голосов
/ 10 июля 2009

Декоратор?

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
0 голосов
/ 10 июля 2009

Это не должно быть более питонным, просто более структурированным:

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...