Python2系で拵えた「踏み台からMySQLをあれこれするプロセス」を3系へ移行してみた

過去にPython2系でトライしてみた「踏み台からMySQLをあれこれするプロセス」を、Python2系のサポート期限を考慮して3系に移行してみました。
2018.11.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

先日「Python2系のサポート期限に備えておきたい事をおさらいしてみる」というエントリーを書きましたが、更に以前書いたエントリー「手作業になりやすい「踏み台サーバ経由でMySQLを実行するプロセス」をコードで完結させてみた」が2系での実装だったことを思い出しました。

Python3系前提で安定して踏み台サーバ経由でMySQLをあれこれしてみるために、依存するライブラリを変更してみました。

利用するアダプタ

今回利用するアダプタはmysqlclientです。前回の2系環境にて利用したMySQL-PythonをForkしたライブラリであり、恐らく検証コストが低いであろうという1点が理由です。

インストール

pipenvで3系の環境にしておきます。

% pipenv install --python 3.6
% pipenv install mysqlclient sshtunnel
% pipenv shell

実装

実行時のコマンドは2系での実装と同じです。

% python main.py

main.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
  
import MySQLdb
import csv
import sshtunnel
import configparser

db_conf = {}
config = configparser.ConfigParser()
config.read('db.ini')
db_conf.update(config['default'])
 
def get_conf():
    return {
        'host': db_conf['host'],
        'port': 3306,
        'user': db_conf['user'],
        'passwd': db_conf['passwd'],
        'db': db_conf['db'],
        'charset': 'utf8',
    }
     
def dump_to_csv():
     
    column_names = ["title", "id", "name", "description"]
    sql = " ".join(["SELECT", ",".join(column_names), "FROM example"])
    db_conf = get_conf()
 
    with open("dump.csv", "w") as csvfile:
        csv_writer = csv.writer(csvfile)
        csv_writer.writerow(column_names)
 
        try:
            print("SSH Tunnel Start")
            server = sshtunnel.SSHTunnelForwarder(
                ("XX.XX.XX.XX", 22), #踏み台IP
                ssh_username="ec2-user",
                ssh_pkey="~/.ssh/server.pem",
                local_bind_address=('127.0.0.1', 3306),
                remote_bind_address=(db_conf["host"], 3306)
            )
            server.start()
            print("SSH Tunnel Started")
             
            print("MySQL Make Connect")
            db_conf["host"] = '127.0.0.1'
            cnn = MySQLdb.connectG(**db_conf)
            cur = cnn.cursor()
            print("MySQL Maked Connect")
             
            print("SQL executing")
            cur.execute(sql)
            result = cur.fetchall()
            print("SQL executed")
             
            for row in result:
                csv_writer.writerow(row)
                 
            cur.close()
            cnn.close()
 
            server.stop()
            print("SSH Tunnel Stoped")
             
        except Exception as e:
            print(e)
            return
 
if __name__ == "__main__":
   dump_to_csv()

db.ini

[default]
user = xxxx
passwd = xxxx
host = xxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com
db = database

変更点

MySQLdb自体は導入するライブラリを変えただけで、コード上に変更はありませんでした。ただ、3系には存在しない実装として発生するエラーがありました。手直しした箇所は以下の通りです。

execfileをconfigparserに

Python2系に存在したexecfileはPython3系に存在しません。execによる代用方法にて検証してみましたが、シンプルにconfigpaerserによる取り込みへ変更しました。

また、併せてdb.confをdb.iniにして、ファイル内容もini構成へ変更しています。

open時にbyteフラグを省いた

Python2系ではbyteフラグを指定してもstr型で書き出せていたのですが、3系環境ではエラーとなっていたため省きました。

CSV出力時にそのまま渡した

unicodeでの変換時にエラーが発生しており、文字エンコード対処そのものを省きました。

まとめ

幾つかの修正箇所が発生したものの、Python3系の環境でも問題なく動作できることを確認しました。実際に2系から3系へと移植する際の参考になれば幸いです。