如何讓MySQL數(shù)據(jù)庫操作更方便-創(chuàng)新互聯(lián)

這篇文章主要介紹了如何讓MySQL數(shù)據(jù)庫操作更方便,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都創(chuàng)新互聯(lián)基于分布式IDC數(shù)據(jù)中心構(gòu)建的平臺為眾多戶提供遂寧聯(lián)通機房 四川大帶寬租用 成都機柜租用 成都服務器租用。

Python的對MySQL的操作的模塊最好的兩個模塊是:

1. MySQLdb
這是一個老牌的MySQL模塊,它封裝了MySQL客戶端的C語言API,但是它主要支持Python 2.x的版本,后來有人叉了一個版本加入了Python 3的支持,并起名為mysqlclient -python它的pypi包名為mysqlclient,所以通過pip安裝就是pip install mysqlclient

2. PyMySQL
這是一個純Python實現(xiàn)的MySQL客戶端。因為是純Python實現(xiàn),它和Python 3的異步模塊aysncio可以很好的結(jié)合起來,形成了aiomysql模塊,后面我們寫異步爬蟲時就可以對數(shù)據(jù)庫進行異步操作了。

通過以上簡單的對比,我們選擇了PyMySQL來作為我們的數(shù)據(jù)庫客戶端模塊。

我在Python中操作MySQL的時間已經(jīng)有很年了,總結(jié)下來,還是龍卷風里面的那個torndb的封裝使用比較方便.torndb在Python 2.x時代早就出現(xiàn)了,那時候它是對MySQLdb的封裝。后來接觸Python 3和PyMySQL,就自己參考torndb和自己的經(jīng)驗,對PyMySQL進行了一個封裝,并給它起了個很土的名字:ezpymysql

不過,這個很土的名字背后,還是有著讓人省心的方便,希望小猿們能看在它好用的份兒上,別計較它很土的名字。

廢話不多講,代碼接著上!

1.使用示例

首先我們先通過一個使用例子看看它的方便性:

from ezpymysql import Connection
db = Connection(
    'localhost',
    'db_name',
    'user',
    'password'
)
# 獲取一條記錄
sql = 'select * from test_table where id=%s'
data = db.get(sql, 2)
# 獲取多天記錄
sql = 'select * from test_table where id>%s'
data = db.query(sql, 2)
# 插入一條數(shù)據(jù)
sql = 'insert into test_table(title, url) values(%s, %s)'
last_id = db.execute(sql, 'test', 'http://a.com/')
# 或者
last_id = db.insert(sql, 'test', 'http://a.com/')
# 使用更高級的方法插入一條數(shù)據(jù)
item = {
    'title': 'test',
    'url': 'http://a.com/',
}
last_id = db.table_insert('test_table', item)

它的使用分兩步:
首先,建立一個MySQL連接;
然后,通過sql語句查詢或插入數(shù)據(jù)。

SQLAchemy之類的ORM呢?簡單說,就是因為這個簡單,我們的操作基本上都是查詢和插入,用基本的選擇,插入這些sql語句是最方便和簡單的。而ORM要先對表建立映射模型,查詢方法也是因ORM而不同,過度的封裝很不適合爬蟲應用場景。其實,老猿我在寫網(wǎng)絡應用時,仍然是自己寫SQL,感覺就是那么的清爽!

好吧,不再賣關(guān)子了,該上ezpymysql的實現(xiàn)了。

2.具體實現(xiàn)

#File: ezpymysql.py
#Author: veelion
"""A lightweight wrapper around PyMySQL.
only for python3
"""
import time
import logging
import traceback
import pymysql.cursors
version = "0.7"
version_info = (0, 7, 0, 0)
class Connection(object):
    """A lightweight wrapper around PyMySQL.
    """
    def __init__(self, host, database, user=None, password=None,
                 port=0,
                 max_idle_time=7 * 3600, connect_timeout=10,
                 time_zone="+0:00", charset = "utf8mb4", sql_mode="TRADITIONAL"):
        self.host = host
        self.database = database
        self.max_idle_time = float(max_idle_time)
        args = dict(use_unicode=True, charset=charset,
                    database=database,
                    init_command=('SET time_zone = "%s"' % time_zone),
                    cursorclass=pymysql.cursors.DictCursor,
                    connect_timeout=connect_timeout, sql_mode=sql_mode)
        if user is not None:
            args["user"] = user
        if password is not None:
            args["passwd"] = password
        # We accept a path to a MySQL socket file or a host(:port) string
        if "/" in host:
            args["unix_socket"] = host
        else:
            self.socket = None
            pair = host.split(":")
            if len(pair) == 2:
                args["host"] = pair[0]
                args["port"] = int(pair[1])
            else:
                args["host"] = host
                args["port"] = 3306
        if port:
            args['port'] = port
        self._db = None
        self._db_args = args
        self._last_use_time = time.time()
        try:
            self.reconnect()
        except Exception:
            logging.error("Cannot connect to MySQL on %s", self.host,
                          exc_info=True)
    def _ensure_connected(self):
        # Mysql by default closes client connections that are idle for
        # 8 hours, but the client library does not report this fact until
        # you try to perform a query and it fails.  Protect against this
        # case by preemptively closing and reopening the connection
        # if it has been idle for too long (7 hours by default).
        if (self._db is None or
            (time.time() - self._last_use_time > self.max_idle_time)):
            self.reconnect()
        self._last_use_time = time.time()
    def _cursor(self):
        self._ensure_connected()
        return self._db.cursor()
    def __del__(self):
        self.close()
    def close(self):
        """Closes this database connection."""
        if getattr(self, "_db", None) is not None:
            self._db.close()
            self._db = None
    def reconnect(self):
        """Closes the existing database connection and re-opens it."""
        self.close()
        self._db = pymysql.connect(**self._db_args)
        self._db.autocommit(True)
    def query(self, query, *parameters, **kwparameters):
        """Returns a row list for the given query and parameters."""
        cursor = self._cursor()
        try:
            cursor.execute(query, kwparameters or parameters)
            result = cursor.fetchall()
            return result
        finally:
            cursor.close()
    def get(self, query, *parameters, **kwparameters):
        """Returns the (singular) row returned by the given query.
        """
        cursor = self._cursor()
        try:
            cursor.execute(query, kwparameters or parameters)
            return cursor.fetchone()
        finally:
            cursor.close()
    def execute(self, query, *parameters, **kwparameters):
        """Executes the given query, returning the lastrowid from the query."""
        cursor = self._cursor()
        try:
            cursor.execute(query, kwparameters or parameters)
            return cursor.lastrowid
        except Exception as e:
            if e.args[0] == 1062:
                pass
            else:
                traceback.print_exc()
                raise e
        finally:
            cursor.close()
    insert = execute
    ## =============== high level method for table ===================
    def table_has(self, table_name, field, value):
        if isinstance(value, str):
            value = value.encode('utf8')
        sql = 'SELECT %s FROM %s WHERE %s="%s"' % (
            field,
            table_name,
            field,
            value)
        d = self.get(sql)
        return d
    def table_insert(self, table_name, item):
        '''item is a dict : key is mysql table field'''
        fields = list(item.keys())
        values = list(item.values())
        fieldstr = ','.join(fields)
        valstr = ','.join(['%s'] * len(item))
        for i in range(len(values)):
            if isinstance(values[i], str):
                values[i] = values[i].encode('utf8')
        sql = 'INSERT INTO %s (%s) VALUES(%s)' % (table_name, fieldstr, valstr)
        try:
            last_id = self.execute(sql, *values)
            return last_id
        except Exception as e:
            if e.args[0] == 1062:
                # just skip duplicated item
                pass
            else:
                traceback.print_exc()
                print('sql:', sql)
                print('item:')
                for i in range(len(fields)):
                    vs = str(values[i])
                    if len(vs) > 300:
                        print(fields[i], ' : ', len(vs), type(values[i]))
                    else:
                        print(fields[i], ' : ', vs, type(values[i]))
                raise e
    def table_update(self, table_name, updates,
                     field_where, value_where):
        '''updates is a dict of {field_update:value_update}'''
        upsets = []
        values = []
        for k, v in updates.items():
            s = '%s=%%s' % k
            upsets.append(s)
            values.append(v)
        upsets = ','.join(upsets)
        sql = 'UPDATE %s SET %s WHERE %s="%s"' % (
            table_name,
            upsets,
            field_where, value_where,
        )
        self.execute(sql, *(values))

3.使用方法

這個實現(xiàn)是對pymysql的簡單封裝,但提供了一些方便的操作:

1.建立MySQL連接

db = Connection(
    'localhost',
    'db_name',
    'user',
    'password'
)

一般只需要四個參數(shù)就可以建立連接了:

  • 主持人:數(shù)據(jù)庫地址,本節(jié)就是本地主機

  • database:數(shù)據(jù)庫名

  • user:數(shù)據(jù)庫用戶名

  • 密碼:數(shù)據(jù)庫用戶的密碼

后面還有幾個參數(shù)可酌情使用:

  • max_idle_time:MySQL服務器默認8小時閑置就會斷開客戶端的連接;這個參數(shù)告訴客戶端閑置多長時間要重新連接;

  • time_zone:這里默認時區(qū)為0區(qū),你可以設置為自己的時區(qū),比如東8區(qū)+8:00;

  • 字符集:默認為utf8mb4,即支持門司字符的UTF8;

操作數(shù)據(jù)庫

數(shù)據(jù)庫操作分為兩類:讀和寫。
讀操作:使用get()獲取一個數(shù)據(jù),返回的是一個dict,key就是數(shù)據(jù)庫表的字段;使用query()來獲取一組數(shù)據(jù),返回的是一個列表,其中每個項目是一個dict,跟get()返回的字典一樣。
寫操作:使用insert()或execute(),看源碼就知道,inseret就是執(zhí)的別名。

3.高級操作

以table_開頭的方法:

  • table_has()查詢某個值是否存在于表中。查詢的字段最好建立的在MySQL中建立了索引,不然數(shù)據(jù)量稍大就會很慢。

  • table_insert()把一個字典類型的數(shù)據(jù)插入表中。字典的key必須是表的字段。

  • table_update()更新表中的一條記錄。其中,field_where最好是建立了索引,不然數(shù)據(jù)量稍大就會很慢。

感謝你能夠認真閱讀完這篇文章,希望小編分享的“如何讓MySQL數(shù)據(jù)庫操作更方便”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設公司行業(yè)資訊頻道,更多相關(guān)知識等著你來學習!

分享標題:如何讓MySQL數(shù)據(jù)庫操作更方便-創(chuàng)新互聯(lián)
本文鏈接:http://muchs.cn/article46/dpshhg.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、網(wǎng)站改版網(wǎng)站排名、外貿(mào)建站、動態(tài)網(wǎng)站、品牌網(wǎng)站設計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務器托管