2016-05-09 88 views
0

我已經習慣了這樣做:試用SqlAlchemy:這是一個好習慣嗎?

from sqlalchemy.orm import sessionmaker 
from sqlalchemy.engine import create_engine 

Session = sessionmaker() 
engine = create_engine("some connection db string", echo=False) 
Session.configure(bind=engine) 

db_con = Session() 

try: 
    # DB MANIPULATION 
finally: 
    db_con.close() 

這是一個良好的習慣?如果是這樣,爲什麼SQLAlchemy的不允許你簡單地做:

with Session() as db_con: 
    # DB MANIPULATION 

回答

1

不,這不是好習慣。這很容易遺忘,並會使代碼更加混亂。

取而代之,您可以使用contextlib.closing上下文管理器,並使其成爲獲取會話的唯一方法。

# Wrapped in a custom context manager for better readability 
@contextlib.contextmanager 
def get_session(): 
    with contextlib.closing(Session()) as session: 
     yield session 

with get_session() as session: 
    session.add(...) 
+0

我不知道'contextlib'。代碼非常乾淨。但是關於問題的第二部分,在你看來,爲什麼'sqlalchemy'的'Session()'對象沒有'__enter __()'和'__exit __()'內建方法? –

+0

@MarcoSulla我對此沒有意見。可能是因爲「關閉」存在。詢問開發人員 – Daenyth

0

首先,如果您已完成會話對象,則應關閉會話。 session.close會將連接返回到引擎池,如果您退出程序,則應該使用engine.dispose來處置引擎池。

現在你的問題。在大多數情況下,會話將用於長時間運行的應用程序,如Web服務器。集中會話管理的意義何在。例如,在flask-sqlalchemy會話中創建每個Web請求的開始並在請求結束時關閉。

+0

如果您沒有對數據庫的獨佔訪問權限,該怎麼辦? –

+0

我不確定數據庫的獨佔訪問如何進入畫面。只要您有權訪問數據庫,就可以創建一個**引擎**對象,並因此創建一個連接池。 – aviator

+0

池化是有趣的,但我認爲你誤解了它的用法:http://docs.sqlalchemy.org/en/latest/core/pooling.html - 你可以看到,池由引擎創建,並且已經有一個池機制。簡單地說,db_con.close()並不真正處理連接,而是將其返回到池中。相反,您將創建一個會話並始終使用它,如果連接斷開或共享數據庫並且同時連接受限,這不是一個好主意,因此您無法連接並保持連接,因爲您會兩分鐘後被解僱。 –

相關問題