2013-10-04 13 views
5

Tôi đang viết một tập lệnh Python có nghĩa là kéo, xử lý và cập nhật lên cơ sở dữ liệu MySQL.Sử dụng mysqldb và sqlite3 trong cùng một kịch bản Python 2.7: Tôi có nên ném vào khăn không?

Ban đầu, tôi bắt đầu tấn công vấn đề này với các giá trị được phân cách bằng dấu phẩy của cơ sở dữ liệu MySQL, mà tôi sẽ ném vào cơ sở dữ liệu sqlite (sử dụng sqlite3). Tôi sẽ thực hiện việc xử lý bằng Python (2.7), tạo một tệp CSV của đầu ra, mà tôi sẽ tải lại cơ sở dữ liệu MySQL bằng một tập lệnh khác.

Vâng, sau đó tôi nghĩ tôi sẽ cố kéo/đẩy cơ sở dữ liệu MySQL trực tiếp từ tập lệnh Python. Vì vậy, tôi đã cài đặt MySQLdb, và đã đi đến thị trấn trên đó.

Điều tôi đang tìm hiểu bây giờ là số INSERT s của tôi từ cơ sở dữ liệu MySQL (vào cơ sở dữ liệu sqlite) không tham gia theo cách trước đây. Các biểu diễn của các số nguyên bây giờ có một L tacked vào cuối, và giá trị thập phân được thể hiện như một cái gì đó như Decimal('4.00').

Về cơ bản, những thứ mà JOIN độc đáo khi tôi chèn chúng từ tệp CSV hiện không hoạt động tốt.

Câu hỏi của tôi: Tôi có yêu cầu một thế giới đau đớn tiếp tục trên con đường này không, hoặc có cách nào dễ dàng để tìm các thư viện MySQLdb và sqlite3 để chơi cùng nhau không? Nếu không có, sau đó tôi sẽ cài đặt một máy chủ MySQL và cấu trúc lại mã của tôi để chỉ sử dụng MySQL.

+2

Không biết tại sao điều này lại bị bỏ phiếu. Tôi cảm thấy đó là một câu hỏi hay và đáng giá +1. Vì vậy, .. 1. –

Trả lời

5

Mỗi chương trình cơ sở dữ liệu hỗ trợ các loại dữ liệu khác nhau. Các mô-đun python sqlite và mysqldb cố gắng giúp bạn bằng cách thực hiện các chuyển đổi kiểu thích hợp dựa trên các kiểu trường. Vì vậy, nếu cơ sở dữ liệu mysql của bạn có một trường DECIMAL, MySQLdb sẽ trả về trường đó tự động như một đối tượng Decimal Python.

Bạn có thể yêu cầu MySQLdb (và sqlite nếu bạn muốn) để thực hiện chuyển đổi kiểu thích hợp giữa các loại cơ sở dữ liệu và Python. Tùy thuộc vào bạn để xác định loại chuyển đổi nào là thích hợp. Ví dụ, vì cơ sở dữ liệu của bạn có một trường DECIMAL, làm thế nào bạn sẽ đại diện cho giá trị đó trong sqlite mà không có một trường DECIMAL riêng? Có thể bạn sẽ kết thúc bằng cách sử dụng một REAL, nhưng tất nhiên đây không phải là điều tương tự như một DECIMAL mà sẽ duy trì độ chính xác cần thiết.

Vì bạn đã chuyển đổi từ dữ liệu csv, tôi nghi ngờ bạn đã sử dụng loại phao Python, cho biết bạn sẵn sàng chuyển đổi các trường thập phân MySQL sang phao. Trong trường hợp này, bạn có thể yêu cầu MySQLdb thực hiện chuyển đổi từ DECIMAL để nổi trên tất cả các kết quả trường.

Dưới đây là một ví dụ về mã tạo hai bảng, mỗi bảng trong mysqldb và sqlite. Phiên bản MySQL có một trường DECIMAL. Bạn có thể thấy trong hàm query_dbs cách tạo các hàm chuyển đổi của riêng bạn.

#!/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) 

kịch bản trên sẽ xuất ra sau trên máy tính của tôi:

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) 

Điều này được thể hiện, đó là theo mặc định MySQLdb đang trở lại loại thập phân, nhưng có thể bị cưỡng chế trở lại một kiểu khác nhau, phù hợp để sử dụng với sqlite.

Sau đó, khi bạn có tất cả các loại được chuẩn hóa giữa hai cơ sở dữ liệu, bạn sẽ không còn gặp vấn đề với các kết nối.

Tài liệu MySQL MySQL Python là here

+0

Điều này rất hữu ích! Nhiều nghĩa vụ! – John

2

Không có xung đột giữa sqlite3 và MySQLdb, vì vậy bạn có thể sử dụng chúng trong cùng một chương trình. Tuy nhiên, bạn cũng có thể xem xét sử dụng SQLAlchemy, cung cấp giao diện cấp cao hơn cho cả hai loại cơ sở dữ liệu. Khi bạn thấy thực sự thấy vấn đề này, các triệu chứng bạn mô tả cho thấy bạn đang chuyển đổi số thành chuỗi không chính xác - đặc biệt, bạn đang sử dụng repr() thay vì str().

+0

Cool; Tôi đã nhìn thấy SQLAlchemy trong chuyến đi của tôi ở đây. Nó cũng xuất hiện (từ câu trả lời của Austin) mà tôi chưa biết về cách kiểm soát các loại chuyển đổi. (++) – John

Các vấn đề liên quan