Pythonでシングルトンを実装

Pythonでシングルトンメソッドを実装するのに苦労したのでここにメモしておく。

class Singleton:
    _instance = None
    class Inner:pass

    def __init__(self):
        if Singleton._instance is None:
            Singleton._instance = Singleton.Inner()

    def __getattr__(self,attr):
        return getattr(self._instance,attr)
    def __setattr__(self,attr,val):
        return setattr(self._instance,attr,val)


s1 = Singleton()
s1.foo = "hello"
s2 = Singleton()

assert s1.foo == s2.foo

sphinxを使ってドキュメントをコードから自動生成する。

コードからドキュメントから自動生成するには以下のコマンドを入力すれば良い。

sphinx-apidoc -F -o docs/ path/to/your/library

あとは

cd docs
make html
open _build/html

とすればドキュメンテーションがちゃんと読める。

これを使って自分がよく使うライブラリのドキュメントはdocs以下のディレクトリに一元化しておくとかすると メリットがありそうなので早速やってみる。

インターネット上にある画像を自分のところにダウンロードする

Python3.4にてhttp上にある画像をダウンロードしたかったのでメモ。

requestsというライブラリを使うと簡単にできた。

import uuid
import requests
import io

response = requests.get("http://path/to/url")
img_data = io.BytesIO(response.content)
img = Image.open(img_data)
uu = str(uuid.uuid1())
filename = "{}.png".format(uu)

# /tmp/img というフォルダーに保存する
path = os.path.join(os.path.abspath("."),"tmp","img",filename)

fp = open(path, "wb")
fp.write(response.content)
fp.close()

FlaskではじめるTDD

今までTDDをやったことなかった。これからはちゃんと保守可能なコードを書いていきたいという 気持ちが生まれたのでテストコードを書くことに決めた。とりあえず単体テストから始めていく。

実装

import json

@app.route("/api/users/hello")
def hello():
    d = {
        "name":"hello"
    }
    return Response(json.dumps(d),mimetype='application/json')

テスト

import ast
from flask import Flask
import json
import unittest

class ReqTestCase(unittest.TestCase):

    def setUp(self):
        self.app = Flask(__name__)
        self.app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:////tmp/app.db"
        self.db = SQLAlchemy(self.app)


    def test_hello(self):
       """
      /api/users/helloにGETリクエストを投げたら、helloが返ってくる。
       """
        with self.app.test_client() as client:
            res = client.get("/api/users/hello")
            res.headers['Content-Type'] = 'application/json'
            data_str = res.data.decode("utf-8")
            data_dict = ast.literal_eval(data)
            self.assertEqual("hello",data_dict.get("name"))


 if __name__ == "__main__":
        unittest.main()

今までリクエスト周りのテストは書いてなかったけど、 こうやってリクエスト周りのテストを書くと純粋なデータのやり取りの実装から進めていくことができて変更に対応しやすいコードが書けそうな感じがある。

ビューとデータの密接な結合が生じているとテストコードを書きにくいことを改めて実感するいい機会になった。