簡體   English   中英

Python的MySQLdb的上下文管理器

[英]Context manager for Python's MySQLdb

我習慣(被寵壞了?)python的SQLite接口來處理SQL數據庫。 python的SQLite API中的一個很好的功能是“上下文管理器”,即python的with語句。 我通常以下列方式執行查詢:

import as sqlite

with sqlite.connect(db_filename) as conn:
    query = "INSERT OR IGNORE INTO shapes VALUES (?,?);"
    results = conn.execute(query, ("ID1","triangle"))

使用上面的代碼,如果我的查詢修改了數據庫並且我忘記運行conn.commit() ,則上下文管理器在退出with語句時會自動為我運行它。 它還可以很好地處理異常:如果在我提交任何內容之前發生異常,則回滾數據庫。

我現在正在使用MySQLdb接口,它似乎不支持MySQLdb即用的類似上下文管理器。 我如何創建自己的? 還有一個相關的問題在這里 ,但它並沒有提供一個完整的解決方案。

以前 ,MySQLdb連接是上下文管理器。 但是, 在2018-12-04的提交中,MySQLdb連接不再是上下文管理器,用戶必須顯式調用conn.commit()或conn.rollback(),或者編寫自己的上下文管理器,如下面的那個。


你可以使用這樣的東西:

import config
import MySQLdb
import MySQLdb.cursors as mc
import _mysql_exceptions
import contextlib
DictCursor = mc.DictCursor
SSCursor = mc.SSCursor
SSDictCursor = mc.SSDictCursor
Cursor = mc.Cursor

@contextlib.contextmanager
def connection(cursorclass=Cursor,
               host=config.HOST, user=config.USER,
               passwd=config.PASS, dbname=config.MYDB,
               driver=MySQLdb):
    connection = driver.connect(
            host=host, user=user, passwd=passwd, db=dbname,
            cursorclass=cursorclass)
    try:
        yield connection
    except Exception:
        connection.rollback()
        raise
    else:
        connection.commit()
    finally:
        connection.close()

@contextlib.contextmanager
def cursor(cursorclass=Cursor, host=config.HOST, user=config.USER,
           passwd=config.PASS, dbname=config.MYDB):
    with connection(cursorclass, host, user, passwd, dbname) as conn:
        cursor = conn.cursor()
        try:
            yield cursor
        finally:
            cursor.close()


with cursor(SSDictCursor) as cur:
    print(cur)
    connection = cur.connection
    print(connection)
    sql = 'select * from table'
    cur.execute(sql)
    for row in cur:
        print(row)

要使用它,您可以在您的PYTHONPATH中放置config.py並在那里定義HOST,USER,PASS和MYDB變量。

自從這個問題最初被問到以后,認為事情已經改變 有點令人困惑(至少從我的觀點來看),對於MySQLdb最新版本,如果在上下文中使用連接,則會得到一個游標(根據oursql示例),而不是自動關閉的東西(就像你打開時一樣)例如一個文件)。

這是我做的:

from contextlib import closing
with closing(getConnection()) as conn: #ensure that the connection is closed
    with conn as cursor:               #cursor will now auto-commit
        cursor.execute('SELECT * FROM tablename')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM