10

मैं एक एसक्लाइट डीबी (सरल सीआरयूडी ऑपरेशंस) को लपेटने के लिए एक छोटा जीयूआई एप्लीकेशन डिज़ाइन कर रहा हूं। मैं (एक /models फ़ोल्डर में m_person, m_card.py, m_loan.py, सभी) तीन SQLAlchemy मॉडल बनाया है और पहले से हर एक के शीर्ष पर निम्न कोड था:क्या मॉड्यूल आयात करते समय कोड निष्पादित करना ठीक है?

from sqlalchemy import Table, Column, create_engine 
from sqlalchemy import Integer, ForeignKey, String, Unicode 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import backref, relation 

engine = create_engine("sqlite:///devdata.db", echo=True) 
declarative_base = declarative_base(engine) 
metadata = declarative_base.metadata 

इसमें कुछ समय गलत (सूखी) महसूस किया तो यह सुझाव दिया गया था कि मैं इन सभी चीजों को मॉड्यूल स्तर पर ले जाऊं (models/__init__.py में)।

from sqlalchemy import create_engine 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy import Table, Column, Boolean, Unicode 
from settings import setup 

engine = create_engine('sqlite:///' + setup.get_db_path(), echo=False) 
declarative_base = declarative_base(engine) 
metadata = declarative_base.metadata 

session = sessionmaker() 
session = session() 

तो जैसे declarative_base आयात ..और:

from sqlalchemy import Table, Column, Unicode 
from models import declarative_base 


class Person(declarative_base): 
    """ 
    Person model 

    """ 
    __tablename__ = "people" 

    id = Column(Unicode(50), primary_key=True) 
    fname = Column(Unicode(50)) 
    sname = Column(Unicode(50)) 

हालांकि मैं प्रतिक्रिया का एक बहुत है कि इस तरह मॉड्यूल आयात के रूप में क्रियान्वित कोड बुरा है लिया है? मैं ऐसा करने के सही तरीके से एक निश्चित उत्तर की तलाश में हूं क्योंकि ऐसा लगता है कि कोड पुनरावृत्ति को हटाने की कोशिश करके मैंने कुछ अन्य बुरे प्रथाओं को पेश किया है। कोई प्रतिक्रिया वास्तव में उपयोगी होगी।

(नीचे get_db_path() के रूप में यह ऊपर models/__init__.py कोड में कहा जाता है संपूर्णता के लिए settings/setup.py से विधि है।)

def get_db_path(): 

    import sys 
    from os import makedirs 
    from os.path import join, dirname, exists 
    from constants import DB_FILE, DB_FOLDER 

    if len(sys.argv) > 1: 
     db_path = sys.argv[1] 
    else: 
     #Check if application is running from exe or .py and adjust db path accordingly 
     if getattr(sys, 'frozen', False): 
      application_path = dirname(sys.executable) 
      db_path = join(application_path, DB_FOLDER, DB_FILE) 
     elif __file__: 
      application_path = dirname(__file__) 
      db_path = join(application_path, '..', DB_FOLDER, DB_FILE) 

    #Check db path exists and create it if not 
    def ensure_directory(db_path): 
     dir = dirname(db_path) 
     if not exists(dir): 
      makedirs(dir) 

    ensure_directory(db_path) 

    return db_path 
+1

मेरा 2 सी, जबकि आम तौर पर '__init __। Py' में यह कोड कोड डालना ठीक है (यह वही है!), डेटाबेस URL सेट करने के लिए अब तक मुझे गलत लगता है। यह परीक्षण कठिन कर सकता है। ऐसा लगता है कि आपको क्या करना चाहिए मॉड्यूल के लिए 'init()' फ़ंक्शन है। – cha0site

+0

मुझे लगता है कि यहां समस्या यह है कि आधार वर्ग 'declarative_base' गतिशील रूप से बनाया गया है और ऐसा लगता है कि डेटाबेस इंजन पर निर्भर करता है। मुझे नहीं पता कि sqlalchemy कैसे काम करता है, लेकिन डीबी कनेक्शन बनाने से पहले मॉडल कक्षाओं को परिभाषित करना संभव नहीं है ?? मैं शायद ही उस पर विश्वास कर सकता हूं। –

+0

@ निकलासबी। 'Declarative_base'" मेटाडाटा "पर निर्भर करता है जो मूल रूप से कोर स्क्लेक्लेमी इंजन है। यह आवश्यक रूप से डेटाबेस के साथ कोई संबंध नहीं है, हालांकि आप इसे सादगी के लिए एक चुन सकते हैं। – wberry

उत्तर

5

कुछ लोकप्रिय चौखटे (मुड़ एक उदाहरण है) प्रारंभ की एक अच्छा सौदा प्रदर्शन आयात समय पर तर्क। मॉड्यूल सामग्रियों को गतिशील रूप से बनाने में सक्षम होने के लाभ एक कीमत पर आते हैं, उनमें से एक यह है कि आईडीई हमेशा यह तय नहीं कर सकता कि मॉड्यूल में "क्या" है या नहीं।

अपने विशिष्ट मामले में, आप रिफैक्टर करना चाहेंगे ताकि विशेष इंजन आयात समय पर आपूर्ति न हो लेकिन बाद में। आप आयात-समय पर मेटाडेटा और declarative_base कक्षा बना सकते हैं। फिर स्टार्ट-टाइम के दौरान, सभी वर्गों को परिभाषित करने के बाद, आप create_engine पर कॉल करते हैं और परिणाम को sqlalchemy.orm.sessionmaker पर बाध्य करते हैं। लेकिन अगर आपकी ज़रूरतें सरल हैं, तो आपको अब तक जाने की भी आवश्यकता नहीं है।

सामान्यतः, मैं कहूंगा कि यह जावा या सी नहीं है। कार्यों, कक्षाओं और स्थिरांक को परिभाषित करने के अलावा मॉड्यूल स्तर पर चीजों को करने से डरने का कोई कारण नहीं है। आपकी कक्षाएं तब बनाई जाती हैं जब एप्लिकेशन वैसे भी शुरू होता है, एक दूसरे के बाद। कक्षाओं के एक छोटे बंदर-पैचिंग (उसी मॉड्यूल में!), या एक या दो ग्लोबल लुकअप टेबल बनाना, मेरी राय में ठीक है यदि यह आपके कार्यान्वयन को आसान बनाता है

जो मैं निश्चित रूप से टालना चाहता हूं वह आपके मॉड्यूल में कोई भी कोड है जो आपके उपयोगकर्ताओं के लिए आयात के आदेश का कारण बनता है (केवल उपयोग करने के लिए तर्क प्रदान करने के सामान्य तरीके के अलावा), या जो आपके बाहर कोड के व्यवहार को संशोधित करता है मॉड्यूल। फिर आपका मॉड्यूल काला जादू बन जाता है, जिसे पर्ल दुनिया में स्वीकार किया जाता है (एला use strict;), लेकिन मुझे लगता है कि "पायथनिक" नहीं है।

उदाहरण के लिए, यदि आपका मॉड्यूल आयात किए जाने पर sys.stdout के गुणों को संशोधित करता है, तो मैं तर्क दूंगा कि व्यवहार को उस फ़ंक्शन में स्थानांतरित किया जाना चाहिए जिसे उपयोगकर्ता कॉल कर सकता है या नहीं।

2

मैं इसमें भी भाग गया, और डेटाबेस प्रबंधक वर्ग के साथ डेटाबेस डेटाबेस फ़ाइल बनाई, जिसके बाद मैंने एक वैश्विक वस्तु बनाई। इस तरह से कक्षा डेटाबेस को कॉन्फ़िगर करने के लिए मेरी सेटिंग्स.py फ़ाइल से सेटिंग्स पढ़ सकती है, और बेस ऑब्जेक्ट (या सत्र/इंजन) का उपयोग करने के लिए आवश्यक प्रथम श्रेणी वैश्विक ऑब्जेक्ट को प्रारंभ करेगी, जिसके बाद हर कोई इसका पुन: उपयोग करेगा। मैं अपने प्रोजेक्ट से "अधिक आरामदायक महसूस करता हूं।SQLAlchemy ORM का उपयोग कर प्रत्येक वर्ग के शीर्ष पर डेटाबेस आयात डीएम ", जहां डीएम मेरी वैश्विक डेटाबेस वस्तु है, और फिर DM.getBase() आधार वस्तु पाने के लिए

यहाँ मेरी database.py वर्ग है:।

Session = scoped_session(sessionmaker(autoflush=True)) 

class DatabaseManager(): 
    """ 
    The top level database manager used by all the SQLAlchemy classes to fetch their session/declarative base. 
    """ 
    engine = None 
    base = None 

    def ready(self): 
     """Determines if the SQLAlchemy engine and base have been set, and if not, initializes them.""" 
     host='<database connection details>' 
     if self.engine and self.base: 
      return True 
     else: 
      try: 
       self.engine = create_engine(host, pool_recycle=3600) 
       self.base = declarative_base(bind=self.engine) 
       return True 
      except: 
       return False 

    def getSession(self): 
     """Returns the active SQLAlchemy session.""" 
     if self.ready(): 
      session = Session() 
      session.configure(bind=self.engine) 
      return session 
     else: 
      return None 

    def getBase(self): 
     """Returns the active SQLAlchemy base.""" 
     if self.ready(): 
      return self.base 
     else: 
      return None 

    def getEngine(self): 
     """Returns the active SQLAlchemy engine.""" 
     if self.ready(): 
      return self.engine 
     else: 
      return None 

DM = DatabaseManager() 
3

सिद्धांत रूप में वास्तव में अजगर कोड जब एक मॉड्यूल आयात किया जाता है को क्रियान्वित करने के साथ कुछ भी गलत नहीं है, वहाँ है हर एक पायथन मॉड्यूल कि जिस तरह से। मॉड्यूल के सदस्यों को परिभाषित करना, कोड निष्पादित हो रहा है सब के बाद।

काम करता है हालांकि, अपने विशेष रूप से केस का उपयोग करें, मैं आपके कोड बेस में सिंगलटन डेटाबेस सत्र ऑब्जेक्ट बनाने के खिलाफ दृढ़ता से सलाह दूंगा। आप क्षमता टी पर हार जाएंगे o कई चीजें करते हैं, उदाहरण के लिए इकाई आपके मॉडल को इन-मेमोरी SQLite या अन्य प्रकार के डेटाबेस इंजन के विरुद्ध परीक्षण करती है।

documentation for declarative_base पर एक नज़र डालें और ध्यान दें कि उदाहरण declarative_base आपूर्ति कक्षा के साथ मॉडल बनाने में सक्षम हैं जो अभी तक डेटाबेस इंजन से बंधे नहीं हैं। आदर्श रूप से आप ऐसा करना चाहते हैं और उसके बाद किसी प्रकार का कनेक्शन फ़ंक्शन या क्लास है जो सत्र बनाने का प्रबंधन करेगा और फिर इसे आधार पर बांध देगा।

+0

यदि मैं सही ढंग से समझता हूं, तो आप सलाह देते हैं कि सत्र ऑब्जेक्ट न बनाएं और फिर इसे चारों ओर पास करें, लेकिन हर बार एक नया सत्र बनाने के लिए मुझे इसका उपयोग करने की आवश्यकता है? – johnharris85

+0

नहीं, आप एक बना सकते हैं और इसे पास कर सकते हैं, बस मॉड्यूल स्तर पर इसे न बनाएं। आपके पास मॉड्यूल स्तर पर 'सत्रमेकर' या उसके रैपरों में से एक श्रेणी लौटाई जा सकती है, लेकिन उस वर्ग के मॉड्यूल-स्तरीय इरादे नहीं हैं। –

2

आयात समय पर कोड निष्पादित करने में कुछ भी गलत नहीं है।

दिशानिर्देश पर्याप्त निष्पादन कर रहा है ताकि आपका मॉड्यूल उपयोग योग्य हो, लेकिन इतना आयात नहीं करना कि यह आयात करना अनावश्यक रूप से धीमा है, और इतना नहीं है कि आप अनावश्यक रूप से सीमित हैं कि इसके साथ क्या किया जा सकता है।

आमतौर पर इसका अर्थ कक्षाओं, कार्यों और वैश्विक नामों (वास्तव में मॉड्यूल स्तर - वहां एक गलत नामक का बिट) परिभाषित करना है, साथ ही साथ अपनी कक्षाओं, कार्यों आदि को आयात करने की आवश्यकता है।

यह आमतौर पर डेटाबेस, वेबसाइट, या अन्य बाहरी, गतिशील संसाधनों से कनेक्शन बनाने में शामिल नहीं होता है, बल्कि मॉड्यूल उपयोगकर्ता ऐसा करने के लिए तैयार होने पर उन कनेक्शनों को स्थापित करने के लिए एक फ़ंक्शन की आपूर्ति करता है।