2010-07-23 13 views
12

मैं एक बनाना चाहता हूं: स्मृति: पायथन में डेटाबेस और विभिन्न धागे से इसका उपयोग करें। अनिवार्य रूप से की तरह कुछ:साझा करना: स्मृति: sqlite3 पैकेज का उपयोग कर पायथन में विभिन्न धागे के बीच डेटाबेस

class T(threading.Thread): 
    def run(self): 
     self.conn = sqlite3.connect(':memory:') 
     # do stuff with the database 

for i in xrange(N): 
    T().start() 

और सभी कनेक्शनों एक ही डाटाबेस की चर्चा करते हुए की है।

मुझे कनेक्ट फ़ंक्शन में check_same_thread=True पास करने और धागे के बीच कनेक्शन साझा करने के बारे में पता है, लेकिन यदि संभव हो तो ऐसा करने से बचना चाहूंगा। किसी भी मदद के लिए धन्यवाद।

संपादित करें: एक टाइपो को सही किया गया। मैंने मूल रूप से कहा "डेटाबेस के लिए धागे को प्रतिस्थापित करने के लिए सभी कनेक्शन एक ही धागे का जिक्र करते हैं"।

+0

आप परिदृश्य, जिसके लिए यह आवश्यक हो तो बताएं कर सकते हैं: यहाँ ड्रॉप-में sqlite3 मॉड्यूल प्रतिस्थापन जाता है? कई धागे से स्क्लाइट का उपयोग करने के बजाय अन्य विकल्प हो सकते हैं? –

+1

@ मुहम्मद अहमकरौरी मुझे यूनिट परीक्षण के लिए एक बहु थ्रेडेड डेटाबेस एप्लिकेशन की आवश्यकता थी। अगर एक फ़ाइल का उपयोग किया जाता है (जैसा कि यह वास्तविक अनुप्रयोग में होगा) तो मैं ठीक से ठीक से कई कनेक्शन खोल सकता हूं। मैंने डाटाबेस लॉजिक को एक थ्रेड में लपेट लिया जो उपभोक्ता पैटर्न का उपयोग करता है और अनुरोध पर पहुंचने पर स्थगित लौटाता है। – aaronasterling

उत्तर

6

हैकिंग sqlite3 लाइब्रेरी के बिना ही आप :memory: डेटाबेस का पुन: उपयोग नहीं कर सकते हैं, क्योंकि यह प्रत्येक कनेक्शन के लिए अनन्य और निजी होने की गारंटी है। इसे एक्सेस करने के लिए, sqlite3 वितरण (पायथन मॉड्यूल वितरण नहीं) में src/pager.c पर नज़दीक देखें। शायद, इसे लागू करने का सबसे सुविधाजनक तरीका :memory:00, :memory:something, :memory:okay_hai इत्यादि कुछ सरल सी-साइड मैपिंग के माध्यम से विभिन्न pPager->memDb पॉइंटर्स को संबोधित करने के लिए उपनाम बनाएगा।

+0

हाय वहाँ, लगभग 4 साल बाद इस पर कोई नई जानकारी? क्या यह अभी भी पाइथन में मौजूदा sqlite3 के साथ संभव नहीं है? – compostus

+0

@compostus, अब डेटाबेस यूआरआई निर्दिष्ट करने के साथ यह संभव है, इस http://www.sqlite.org/uri.html का संदर्भ लें, 'मोड = मेमोरी' और' कैश = साझा' 'देखें। – toriningen

+0

@compostus, इस प्रश्न का मेरा नया उत्तर देखें। – toriningen

25

SQLite पिछले 4 वर्षों में सुधार हुआ था, इसलिए अब इन-मेमोरी डेटाबेस साझा किए गए हैं। निम्नलिखित कोड की जाँच करें:

import sqlite3 

foobar_uri = 'file:foobar_database?mode=memory&cache=shared' 
not_really_foobar_uri = 'file:not_really_foobar?mode=memory&cache=shared' 

# connect to databases in no particular order 
db2 = sqlite3.connect(foobar_uri, uri=True) 
db_lol = sqlite3.connect(not_really_foobar_uri, uri=True) 
db1 = sqlite3.connect(foobar_uri, uri=True) 

# create cursor as db2 
cur2 = db2.cursor() 

# create table as db2 
db2.execute('CREATE TABLE foo (NUMBER bar)') 

# insert values as db1 
db1.execute('INSERT INTO foo VALUES (42)') 
db1.commit() 

# and fetch them from db2 through cur2 
cur2.execute('SELECT * FROM foo') 
print(cur2.fetchone()[0]) # 42 

# test that db_lol is not shared with db1 and db2 
try: 
    db_lol.cursor().execute('SELECT * FROM foo') 
except sqlite3.OperationalError as exc: 
    print(exc) # just as expected 

डाटाबेस पहुंच जानबूझकर उलझ रहे हैं, पता चलता है कि एक ही नाम के साथ में स्मृति डेटाबेस के लिए दो कनेक्शन देखने के SQLite के दृष्टिकोण से ही हैं।

संदर्भ:

  1. SQLite URIs
  2. SQLite shared cache

दुर्भाग्य से, URI के आधार पर कनेक्शन अजगर 3.4 के बाद से ही उपलब्ध है। हालांकि, अगर आपके पास पाइथन 2.6 या बाद में (लेकिन पायथन 3 नहीं है), sqlite3 मॉड्यूल निर्मित अभी भी एपीएसडब्ल्यू कनेक्शन आयात करने में सक्षम है, जिसका उपयोग उसी प्रभाव को प्राप्त करने के लिए किया जा सकता है।

from sqlite3 import * 
from sqlite3 import connect as _connect 
from apsw import Connection as _ApswConnection 
from apsw import SQLITE_OPEN_READWRITE as _SQLITE_OPEN_READWRITE 
from apsw import SQLITE_OPEN_CREATE as _SQLITE_OPEN_CREATE 
from apsw import SQLITE_OPEN_URI as _SQLITE_OPEN_URI 

# APSW and pysqlite use different instances of sqlite3 library, so initializing 
# APSW won't help pysqlite. Because pysqlite does not expose any way to 
# explicitly call sqlite3_initialize(), here goes an ugly hack. This only has 
# to be done once per process. 
_connect(':memory:').close() 

def connect(database, timeout=5.0, detect_types=0, isolation_level=None, 
      check_same_thread=True, factory=Connection, cached_statements=100, 
      uri=False): 
    flags = _SQLITE_OPEN_READWRITE | _SQLITE_OPEN_CREATE 

    if uri: 
     flags |= _SQLITE_OPEN_URI 

    db = _ApswConnection(database, flags, None, cached_statements) 
    conn = _connect(db, timeout, detect_types, isolation_level, 
        check_same_thread, factory, cached_statements) 

    return conn 
+0

thanx बहुत कुछ! मैं पाइथन 3.3 डॉक्स देख रहा था, इसलिए मैंने 'sqlite3.connect()' के 'uri' विकल्प को अनदेखा किया, जो केवल Python 3.4 ** के बाद उपलब्ध है। – compostus

+0

@ कॉम्पोस्टस, आपका स्वागत है! – toriningen

+0

अभी भी पाइथन 2.7 पर किसी के लिए सबसे अच्छा विकल्प (यदि कोई है) क्या है? – baconwichsand

संबंधित मुद्दे