この記事は公開されてから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系へと移植する際の参考になれば幸いです。