2013-10-04 14 views
5

Bir MySQL veritabanından almak, işlemek ve güncellemek için bir Python komut dosyası yazıyorum.mysqldb ve sqlite3'ü aynı Python 2.7 komut dosyasında kullanma: Havluya atmalı mıyım?

Orijinal olarak bu soruna bir sqlite veritabanına (sqlite3 kullanarak) girdiğim MySQL veritabanlarının virgülle ayrılmış değer dökümleriyle saldırmaya başladım. İşlemi Python'da (2.7) gerçekleştiririm, çıktının bir CSV dosyası oluşturur, bu da MySQL veritabanına başka bir betik ile geri yüklerim.

Peki, o zaman sadece Python komut dosyasından MySQL veritabanını çekmeye/itmeye çalışacağımı düşündüm. Bu yüzden MySQLdb'yi kurdum ve kasabaya gittim.

Şu an bulduklarım, MySQL veritabanımdan (sqlite veritabanına) INSERT s sayfamın daha önce oldukları gibi katılmadıklarıdır. Tamsayıların temsilleri artık sonunda bir L'ye bağlanmış ve ondalık değerler Decimal('4.00') gibi bir şey olarak ifade edilir.

Temel olarak, bunları, CSV dosyalarından eklerken çok güzel bir şekilde edindiğim JOIN artık çok iyi çalışmıyor.

Sorum: Acı dolu bir dünyada soran muyum Bu yolda devam ya da birlikte oynamayı MySQLdb ve Sqlite3 kütüphaneleri almak için kolay bir yol var mı? Eğer yoksa, bir MySQL sunucusunu kuracağım ve yalnızca MySQL kullanmak için kodumu yeniden düzenleyeceğim.

+2

here bu aşağı-neden seçildi Fikrim Yok vardır. İyi bir soru olduğunu ve +1 değerinde olduğunu hissediyorum. Yani .. +1. –

cevap

5

Her veritabanı arka ucu, farklı veri türlerini destekler. Sqlite ve mysqldb python modülleri, alan türlerine göre uygun türde dönüşümler yaparak size yardımcı olmaya çalışır. Yani, eğer mysql veritabanınız bir DECIMAL alanına sahipse, MySQLdb bu alanı otomatik olarak bir Python Decimal nesnesi olarak döndürecektir.

Veritabanı ve Python türleri arasında uygun tür dönüşümü yapmak için MySQLdb (ve isterseniz sqlite) isteyebilirsiniz. Hangi tür dönüşümün uygun olduğunu belirlemek size kalmıştır. Örneğin, veritabanınızın DECIMAL alanı olduğundan, bu değeri yerel bir DECIMAL alanı olmayan sqlite cinsinden nasıl temsil edersiniz? Muhtemelen bir REAL kullanarak sona ereceksin, ama elbette bu gerekli hassasiyeti koruyacak bir DECIMAL ile aynı şey değildir.

Zaten csv verilerinden dönüştürdüğünüz için, MySQL ondalık alanlarını float'a dönüştürmekten mutlu olduğunuzu belirten Python float türünü kullandığınızdan şüpheleniyorum. Bu durumda, MySQLdb'nin tüm alan sonuçlarında yüzdüğü DECIMAL'den bir dönüşüm yapmasını isteyebilirsiniz.

Burada mysqldb ve sqlite öğelerinden biri olmak üzere iki tablo oluşturan bir kod örneği verilmiştir. MySQL sürümü bir DECIMAL alanına sahiptir. Kendi dönüştürme işlevlerinizi nasıl oluşturacağınızı query_dbs işlevinde görebilirsiniz.

#!/usr/bin/env python 

import os 
import sqlite3 
import MySQLdb 
from MySQLdb.constants import FIELD_TYPE 

user = os.getenv('USER') 

def create_mysql_table(): 
    conn = MySQLdb.connect(user=user, db='foo') 
    c = conn.cursor() 
    c.execute("DROP TABLE stocks") 
    c.execute("CREATE TABLE stocks" 
       "(date text, trans text, symbol text, qty real, price Decimal(10,2) UNSIGNED NOT NULL)") 
    c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)") 
    conn.commit() 

def create_sqlite_table(): 
    conn = sqlite3.connect('test.db') 
    c = conn.cursor() 
    c.execute("DROP TABLE stocks") 
    c.execute("CREATE TABLE stocks" 
       "(date text, trans text, symbol text, qty real, price real)") 
    c.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)") 
    conn.commit() 

def query_dbs(use_type_converters): 
    conn = sqlite3.connect('test.db') 
    c = conn.cursor() 
    for row in c.execute('SELECT * FROM stocks'): 
     print 'SQLITE: %s' % str(row) 

    type_converters = MySQLdb.converters.conversions.copy() 

    if use_type_converters: 
     type_converters.update({ 
      FIELD_TYPE.DECIMAL: float, 
      FIELD_TYPE.NEWDECIMAL: float, 
     }) 

    conn = MySQLdb.connect(user=user, db='foo', conv=type_converters) 
    c = conn.cursor() 
    c.execute('SELECT * FROM stocks') 
    for row in c.fetchall(): 
     print 'MYSQLDB: %s' % str(row) 

create_sqlite_table() 
create_mysql_table() 

print "Without type conversion:" 
query_dbs(False) 
print "With type conversion:" 
query_dbs(True) 

Bu komut benim makinede şu çıktıyı üretir: Bu gösteriyor ne

Without type conversion: 
SQLITE: (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14) 
MYSQLDB: ('2006-01-05', 'BUY', 'RHAT', 100.0, Decimal('35.14')) 
With type conversion: 
SQLITE: (u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14) 
MYSQLDB: ('2006-01-05', 'BUY', 'RHAT', 100.0, 35.14) 

, varsayılan olarak MySQLdb Ondalık türlerini dönüyor, ancak farklı bir türü dönmek zorla edilebilmesi, uygundur sqlite ile kullanım içindir. Daha sonra, iki veritabanının arasında normalize edilen tüm türlere sahip olduğunuzda, artık katılma konusunda sorun yaşamanız gerekir. Daha fazla bilgi için bkz: http://support.microsoft.com/downloads/default.aspx (http://www.microsoft.com/downloads/default.aspx?displaylang=tr)

Python MySQLdb docs

+0

Bu çok öğreticidir! Çok minnettarım! – John

2

sqlite3 ve MySQLdb arasında çakışma yoktur, bu nedenle bunları aynı programda kullanabilmeniz gerekir. Ancak, her iki veritabanına da daha üst düzey bir arabirim sağlayan SQLAlchemy kullanmayı düşünebilirsiniz. Özellikle, sen str() yerine repr() kullanmakta olduğunuz -

Bildiğim kadarıyla aslında bu sorunu görüyoruz neden olarak, açıkladığınız belirtiler yanlış dizeleri numaralar dönüştürürüz düşündürmektedir.

+0

Cool; Seyahatlerimde SQLAlchemy'yi gördüm. Aynı zamanda (Austin’in cevabından), tür dönüşümlerini nasıl kontrol edeceğimi öğrenmediğimi de görüyoruz. (++) – John