2013-05-02 4 views
9

में नामित करने के लिए परिणाम पंक्तियों का मानचित्रण करना मैं स्क्लाइट 3 के लिए पायथन एपीआई के साथ थोड़ा सा खेल रहा हूं, मेरे पास आईडी, नाम और निर्माण_डेट फ़ील्ड के साथ स्टोर भाषाओं के लिए एक छोटी सी टेबल है। मैं कच्चे क्वेरी परिणामों को namedtuple में मानचित्रों की अनुशंसा के रूप में मैप करने की कोशिश कर रहा हूं, इस तरह मैं पंक्तियों को अधिक पठनीय तरीके से प्रबंधित कर सकता हूं, इसलिए यहां मेरा namedtuple है।पाइथन एसक्लाइट

LanguageRecord = namedtuple('LanguageRecord', 'id, name, creation_date') 

कोड कि डॉक्स मानचित्रण के लिए सुझाव है कि इस प्रकार है:

for language in map(LanguageRecord._make, c.fetchall()): 
    # do something with languages 

यह ठीक है जब मैं भाषाओं का एक संग्रह वापस जाने के लिए चाहते हैं, लेकिन इस मामले में मैं सिर्फ एक प्राप्त करना चाहते हैं भाषा:

:

c.execute('SELECT * FROM language WHERE name=?', (name,)) 

तो मेरी पहली कोशिश यह कुछ इस तरह था

इस कोड काम करता है नहीं करता है क्योंकि fetchone() एक टपल बजाय एक टपल साथ एक सूची देता है, तो map समारोह प्रत्येक टपल क्षेत्र विचार के लिए तीन namedtuples एक बनाने के लिए प्रयास करता है।

मेरा पहला दृष्टिकोण हल करने के लिए इस तरह कुछ स्पष्ट रूप से एक सूची बना सकते हैं और इसे करने के लिए टपल परिणाम संलग्न करने के लिए, था:

languages = [] 
languages.append(c.fetchone()) 
for language in map(LanguageRecord._make, languages): 
    # do something with language 

मेरे दूसरा दृष्टिकोण fetchall() उपयोग करने के लिए हालांकि मैं सिर्फ एक रिकॉर्ड चाहते थे। मैं नाम फ़ील्ड को unique डेटाबेस में केवल एक परिणाम को गारंट करने के लिए सेट कर सकता हूं।

for language in map(LanguageRecord._make, c.fetchall()): 
    # do something with languages 

एक और दृष्टिकोण सिर्फ एक परिणाम garantize को unique विवश बिना उपयोग fetchall()[0] हो सकता है।

मेरा प्रश्न यह है कि इस समस्या से निपटने का सबसे अच्छा और आम तरीका है, क्या मुझे हमेशा एक सामान्य इंटरफ़ेस बनाए रखने के लिए fetchall का उपयोग करना चाहिए और डेटाबेस को विशिष्टता तर्क प्रबंधित करना चाहिए? या क्या मुझे दृष्टिकोण 1 में स्पष्ट रूप से एक सूची बनाना चाहिए? क्या इस कार्य को पूरा करने का कोई आसान तरीका है?

+0

तुम भी डेटाबेस कर्सर पुनरावृति कर सकते हैं, वहाँ सभी रिकॉर्ड लाने के लिए कोई जरूरत नहीं है, जब तक आप चाहते हैं करने के लिए, इसलिए कोड को 'मानचित्र (LanguageRecord._make, c) 'के रूप में पुनः लिखा जा सकता है। –

उत्तर

19

एक बहुत आसान तरीका है! Sqlite3 उपयोगकर्ता को "row factories" परिभाषित करने का एक तरीका प्रदान करता है। ये पंक्ति कारखानों कर्सर और ट्यूपल पंक्ति लेते हैं और जो कुछ भी वस्तु चाहते हैं उसे वापस कर सकते हैं।

एक बार जब आप

con.row_factory = my_row_factory 

तो पंक्तियों कर्सर द्वारा दिया my_row_factory का परिणाम टपल पंक्ति के लिए लागू किया जाएगा के साथ पंक्ति कारखाने की स्थापना की। उदाहरण के लिए,

import sqlite3 
import collections 

LanguageRecord = collections.namedtuple('LanguageRecord', 'id name creation_date') 
def namedtuple_factory(cursor, row): 
    return LanguageRecord(*row) 

con = sqlite3.connect(":memory:") 
con.row_factory = namedtuple_factory 
cur = con.cursor() 
cur.execute("select 1,2,3") 
print(cur.fetchone()) 

पैदावार

LanguageRecord(id=1, name=2, creation_date=3) 

कैसे एक namedtuple कारखाने परिभाषित करने के लिए, this post देखने का एक और उदाहरण के लिए।


वैसे, आप निर्धारित करते हैं

conn.row_factory = sqlite3.Row 

तो पंक्तियों dicts, जिसका कुंजी तालिका की स्तंभ नाम हैं रूप में वापस आ रहे हैं। इस प्रकार, row.creation_date जैसी चीजों के साथ नामांकित भागों के हिस्सों तक पहुंचने के बजाय आप केवल sqlite3.Row पंक्ति कारखाने का उपयोग कर सकते हैं और row['creation_date'] के बराबर पहुंच सकते हैं।

+1

'sqlite3.Row' वास्तविक नियम नहीं है, क्योंकि यह' .get() 'या' .__ को __() 'लागू नहीं करता है। – rgov

0

मुझे लगता है कि for language in map(LanguageRecord._make, c.fetchall()[:1]): का उपयोग करना बेहतर है क्योंकि यह fetchall() [0] के साथ इंडेक्स एरर का कारण बन सकता है।

यदि आपको एक परिणाम की आवश्यकता है और क्वेरी में पहले से ही "WHERE" है। जैसा कि मैं समझता हूं कि क्वेरी को एक पंक्ति वापस करनी चाहिए। प्रारंभिक अनुकूलन बुरा है। :)

1

एक बेहतर row_factory वास्तव में यह है, जिन तक प्रश्नों के सभी प्रकार के लिए पुन: उपयोग किया जा सकता है:

from collections import namedtuple 

def namedtuple_factory(cursor, row): 
    """Returns sqlite rows as named tuples.""" 
    fields = [col[0] for col in cursor.description] 
    Row = namedtuple("Row", fields) 
    return Row(*row) 

conn = sqlite3.connect(":memory:") 
conn.row_factory = namedtuple_factory 
cur = con.cursor() 
संबंधित मुद्दे