Aplikacje często muszą łączyć się z innymi usługami (bazą danych, pamięcią podręczną, interfejsem API itp.). Dla zdrowia i DRY chcielibyśmy zachować wszystkie te połączenia w jednym module, aby reszta naszej bazy kodowej mogła współdzielić połączenia.Zarządzanie tworzeniem połączeń w Pythonie?
Aby zmniejszyć boilerplate, za użytkowanie powinno być proste:
# app/do_stuff.py
from .connections import AwesomeDB
db = AwesomeDB()
def get_stuff():
return db.get('stuff')
i konfiguracja połączenia powinny być również prosta:
# app/cli.py or some other main entry point
from .connections import AwesomeDB
db = AwesomeDB()
db.init(username='stuff admin') # Or os.environ['DB_USER']
sieci ram takich jak Django i kolby zrobić coś takiego, ale czuje się trochę niezgrabnie:
Connect to a Database in Flask, Which Approach is better? http://flask.pocoo.org/docs/0.10/tutorial/dbcon/
Jednym dużym problemem jest to, że chcemy odwoływać się do rzeczywistego obiektu połączenia zamiast do serwera proxy, ponieważ chcemy zachować tab-completion w iPython i innych środowiskach programistycznych.
To, co jest właściwym sposobem (tm) to zrobić? Po kilku iteracjach, oto mój pomysł:
#app/connections.py
from awesome_database import AwesomeDB as RealAwesomeDB
from horrible_database import HorribleDB as RealHorribleDB
class ConnectionMixin(object):
__connection = None
def __new__(cls):
cls.__connection = cls.__connection or object.__new__(cls)
return cls.__connection
def __init__(self, real=False, **kwargs):
if real:
super().__init__(**kwargs)
def init(self, **kwargs):
kwargs['real'] = True
self.__init__(**kwargs)
class AwesomeDB(ConnectionMixin, RealAwesomeDB):
pass
class HorribleDB(ConnectionMixin, RealHorribleDB):
pass
pokój dla poprawy: Ustaw początkowy __connection do rodzajowego ConnectionProxy zamiast Żaden, który przyciąga wszelki dostęp atrybutu i zgłasza wyjątek.
Zrobiłem sporo pogwizdywania tutaj na SO i różnych projektach OSS i nie widziałem czegoś takiego. Czuje się dość solidnie, choć oznacza to, że kilka modułów będzie tworzyło obiekty połączeń jako efekt uboczny w czasie importu. Czy to wysadzi w moją twarz? Czy istnieją inne negatywne konsekwencje tego podejścia?
Dzięki za dokładną odpowiedź! Naprawdę nie uważałem bezpieczeństwa nitek i wideł, na pewno o tym pomyślę. Re: parametry połączenia błąd, dobry połów i dobre rozwiązanie. Re: Pule klientów, również dobre, ale nawet z pulą połączeń, należy scentralizować inicjalizację i zagwarantować, że używasz tej samej puli w całej aplikacji. – knite
Re: prosta funkcja pomocnika, początkowo rozważałem to podejście. Szybko staje się to denerwujące z powodu tego, że każdy moduł musi importować awesome_db * i * wywoływać go. – knite