updated on 2021-04-04
mysql-connector-pythonでMySQLに接続するクラスを共通クラスとして部品化して再利用できるようにする
筆者の環境
Pythonプログラムからデータベースにアクセスするためのライブラリの一つ
$ pip3 install mysql-connector-python
import mysql.connector as mydb # コネクションの作成 import conn = mydb.connect( host='localhost', port='3306', user='root', password='password', database='dbname' ) # コネクションが切れた時に再接続してくれるよう設定 conn.ping(reconnect=True) # DB操作用にカーソルを作成 cur = conn.cursor()
table = 'test_table' cur.execute("DROP TABLE IF EXISTS `%s`;", table) cur.execute( """ CREATE TABLE IF NOT EXISTS `%s` ( `id` int auto_increment primary key, `name` varchar(50) not null, `price` int(11) not null ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci """, table) )
cur.execute("INSERT INTO test_table VALUES (1, 'BTC', 10200)") # プレースホルダを利用して挿入 cur.execute("INSERT INTO test_table VALUES (2, 'ETH', %s)", (5000, )) cur.execute("INSERT INTO test_table VALUES (%s, %s, %s)", (3 ,'XEM', 2500)) cur.execute("INSERT INTO test_table VALUES (%(id)s, %(name)s, %(price)s)", {'id': 4, 'name': 'XRP', 'price': 1000}) # executemanyで複数データを一度に挿入 records = [ (5, 'MONA', 3000), (6, 'XP', 1000), ] cur.executemany("INSERT INTO test_table VALUES (%s, %s, %s)", records)
cur.execute("SELECT * FROM test_table ORDER BY id ASC") # 全てのデータを取得 rows = cur.fetchall() for row in rows: print(row) # 出力結果 """ (1, 'BTC', 10200) (2, 'ETH', 5000) (3 ,'XEM', 2500) (4, 'XRP', 1000) (5, 'MONA', 3000) (6, 'XP', 1000) """ # 1件取得 cur.execute("SELECT * FROM test_table WHERE name=%s", ('BTC', )) print(cur.rowcount) print(cur.fetchone()) # 出力結果 """ 1 (1, 'BTC', 10200) """
# UPDATE cur.execute('UPDATE test_table SET name=%s WHERE id=1', ('ビットコイン',)) cur.execute('UPDATE test_table SET name=%s WHERE id=%s', ('イーサリアム', 2))
# DELETE cur.execute('DELETE FROM test_table WHERE id = 3')
# カーソルとコネクションを閉じる
cur.close()
conn.close()
- MySQLとの接続が必要な時に、毎度、下記のコードを書いて、接続情報を生成するのは非常に手間
- DB設定の修正を行う際に、関連するコードを全て修正しなければならないので、かなり苦痛、修正漏れとか出しそう
- そもそもエンジニアとして、同じことを2回するのがいや
# コネクションの作成 conn = mydb.connect( host='localhost', port='3306', user='root', password='password', database='dbname' ) ...
ということで、いざ、MySQLの操作用のクラスを作成
(mysql_connector.py)
import mysql.connector as mydb import sys # # DBアクセス管理クラス # class MysqlConnector: # ----------------------------------- # コンストラクタ # # コネクションを取得し、クラス変数にカーソルを保持する。 # ----------------------------------- def __init__(self, host='localhost', port='3306', user='root', password='password', database='dbname'): try: self.conn = mydb.connect( host=host, port=port, user=user, password=password, database=database ) # コネクションの設定 self.conn.ping(reconnect=True) self.conn.autocommit = False # カーソル情報をクラス変数に格納 self.cur = self.conn.cursor() # 接続できているかどうか確認 # print(self.conn.is_connected()) except (mydb.errors.ProgrammingError) as e: print(e) sys.exit(1) # ----------------------------------- # クエリの実行 # # クエリを実行し、取得結果を呼び出し元に通知する。 # ----------------------------------- def fetch(self, sql): try: self.cur.execute(sql) rows = self.cur.fetchall() return rows except mydb.Error as e: print(e) sys.exit(1) # ----------------------------------- # インサートの実行 # # インサートを実行する。 # ----------------------------------- def insert(self, sql): try: self.cur.execute(sql) self.conn.commit() except (mysql.connector.errors.ProgrammingError) as e: self.conn.rollback() print(e) sys.exit(1) # ----------------------------------- # アップデートの実行 # # アップデートを実行する。 # ----------------------------------- def update(self, sql): try: self.cur.execute(sql) self.conn.commit() except (mysql.connector.errors.ProgrammingError) as e: self.conn.rollback() print(e) sys.exit(1) def delete(self, sql): try: self.cur.execute(sql) self.conn.commit() except (mysql.connector.errors.ProgrammingError) as e: self.conn.rollback() print(e) sys.exit(1) def close(self): self.cur.close() self.conn.close() def debug_conn(self): print(self.conn.is_connected())
接続
from yourmodulename.mysql_connector import MysqlConnector connector = MysqlConnector() # インスタンスを生成
ホスト名やユーザー名を、デフォルトから変更するなら、インスタンス作成時に引数に設定する
connector = MysqlConnector(host='myhost', port='myport', user='myuser', password='mypassword', database='mydb')
SELECT
rows = connector.fetch("SELECT * FROM universities limit 5;") # 確認 for row in rows: print(row)
insert
connector.insert("INSERT INTO circles(`id`, `name`, `university_id`) VALUES('1', 'サッカー', '1');")
update
connector.update("UPDATE circles SET name = 'ラグビー' WHERE id = 1;")
delete
connector.delete("DELETE FROM circles WHERE id = 1;")
接続確認
connector.debug_conn()
最後
connector.close()
コード(DB機能提供側) は、再利用して楽する為に、丸コピして、使ってみてください。
また、python-mysql-connectorは導入が簡単な反面、再利用の設計を考えると、工数かけて設計しないと行けなくなるので、簡易的なプロジェクト以外の場合は、pythonで使えるORMの使用を検討するべきだということがわかりました。