0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PyMySQLで任意のDictCursorを作って、NULLのときにNoneを返さない方法

Posted at

前置き

PyMySQL使ってますか?
え?ORM使ってるからそんなもん使わない?

まぁまぁ、ORMはORMでめんどくさいときがあるじゃないですか。
チョクでSQL書いたら楽なときもあるでしょ?

でPyMySQL

import pymysql.cursors

# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='user',
                             password='passwd',
                             db='db',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

with connection.cursor() as cursor:
        # Create a new record
        sql = "SELECT * from users where first_name = 'bob'"
        cursor.execute(sql, connection)

とか。

cursorclass=pymysql.cursors.DictCursor ってのが便利です。


{'name': 'bob', 'id': 1}

のようにDictを返してくれるからです。

でもこれ。NULLがあるとこうなるんですわ。


[{'first_name': 'bob', 'last_name': 'smith', 'id': 1, 'phone_num': None},
{'first_name': 'bob', 'last_name': 'jones', 'id': 2, 'phone_num': None}]

None じゃなくて"NULL"って返してほしい。
NULLのときは"NULL"って返せって仕様書にあるんだもん。

んで戻り値をfor i in ...: とかやって置き換えてませんか?

ソースコード

DictCursorってなにやってんの?

class DictCursor(DictCursorMixin, Cursor):
    """A cursor which returns results as a dictionary"""

なんも。
DictCursorMixinは?

class DictCursorMixin(object):
    # You can override this to use OrderedDict or other dict-like types.
    dict_type = dict

「Dict-likeでオーバーライドしてね!」と。

テストでもやってるからやっていいんでしょうね

じゃあ

d = {"foo": "bar", "baz": None}

assert d["baz"] == "NULL"

こういうDict作ればいいんじゃね?

class MyDict(dict):
    def __init__(self):
        # なんか処理する

とりあえずこんな感じ? dunderいじくりたいのですが、dictってどんな実装になってるんでしょうね・・・・

ここみると・・・ソースがCなので読めないっす。(つよつよな方は読めるんでしょうが・・・)

「OrderedDictとか入れてね」ってソースにあるのでOrderdDictのソースを・・・

OrderedDictでもいいかな

class OrderedDict(dict):
    def __init__(self, other=(), /, **kwds):
        # (略)
        self.__update(other, **kwds)

updateはこっち?だけどいまいちよくわかんないので適当に実装します。

まとめ

class MyDict(dict):
    def __init__(self, other=None):
        super().__init__()
        self._update(other)

    def _update(self, other=None):
        if other is not None:
            for h, i in other:
                if i:
                    self[h] = i
                else:
                    self[h] = "NULL"

class MyDictCursor(cursors.DictCursor):
    dict_type = MyDict

connection = pymysql.connect(host='localhost',
                             user='user',
                             password='passwd',
                             db='db',
                             charset='utf8mb4',
                             cursorclass=MyDict)

んでこうなると。

[{'first_name': 'bob', 'last_name': 'smith', 'id': 1, 'phone_num': "NULL"},
{'first_name': 'bob', 'last_name': 'jones', 'id': 2, 'phone_num': "NULL"}]
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?