【Python】throwされたErrorのメッセージをconsoleに表示
概要
Errorメッセージをconsoleに表示して何がおきているか確認する。
解決方法
for model in models: try: // 処理 print("success); except Exception as e: print("message : %s" % e) pass
【Python】AttributeError: 'dict' object has no attribute 'iteritems'
概要
以下のエラーが出たので対応。
AttributeError: 'dict' object has no attribute 'iteritems'
解決策
iteritems()
からitems()
にする。
【Python】NameError: name 'unicode' is not defined
【Python】issubclassでTrueを期待するのにFalseが返ってくる
概要
issubclass
を使っていて、Trueを期待するのにFalseが返って来て頭がおかしくなりそうになった。
時間をかけた割に大したことを得られなかった悲しさをこのブログにぶつける。
本題
ある復刻プロジェクトをやっているのだが、そのシステムではdynamoDBを利用している。
dynamoDBを利用するためにはbotoというライブラリを利用しているが、せっかくやるのでboto
もboto3
にアップデートすることに決めた。
boto
を利用する際は、さらにbotoの扱いを抽象化するdynamodb_mapper
というものを利用していたが、dynamodb_mapper
は最終リリースが2013年であり、更にboto3
に対応していないため自分でboto3
用のmapperを書かなければいけなかった。
とりあえず動かせそうなmapperを作成して動作確認をしている時に問題が起きた。
ここでmapperのクラス名はDynamoDBModel
で、以下のようにしてimportしている。
from dynamodb_mapper.model import DynamoDBModel
そして、今回model_boto3
というファイルでmapperを作成したので、以下のようにimport文を書き換える。
from dynamodb_mapper.model_boto3 import DynamoDBModel
新mapperを作ったが、class名はもちろんのことメソッドのインターフェースを変えていないところが自身のこだわったというか、意識した部分だ(コードをきれいにしたらmapperは公開しようと思う)。 しかし、このことが災いを引き起こすなんて思ってもみなかった。
プロジェクトで実際にdynamoDBを利用するためのModelでは、DynamoDBModel
クラスを継承している。
以下のようなかんじで。
class Hoge(DynamoDBModel)
このように継承しているのは、システム中で利用しているDBはdynamoDBだけでなくMySQLも利用しており、ModelがDynamoDBModel
を継承しているか、MySQL用のクラスを継承しているかによって処理を分けるためだ。
さて、この処理を分ける部分だが、以下のようにしてDynamoDBModel
を継承しているかを判断していた。DynamoDBModel
のimportではdynamodb_mapper.model_boto3
を指定しているし、issubclass()で指定しているDynamoDBModel
の部分にマウスポインタを当てると、vscodeがこの型はdynamodb_mapper.model_boto3
のDynamoDBModel
ですよって教えてくれているし、これで完璧でしょ、と思った。しかしながら現実はfalse。
issubclass([Hogeのインスタンス], (DynamoDBModel,))
issubclass
の使い方が間違っているのかな、と思ったのだが全然間違ってなさそうだし、DynamoDBModel
はdynamodb_mapper.model_boto3
なはずだし、何が悪いのかがさっぱりわからなかった。
と、悩んだり調べたりして2時間経った時にDynamoDBModel
はカーソルを乗っけるとdynamodb_mapper.model_boto3
って出てくるけど実は旧DynamoDBModelのdynamodb_mapper.model
を参照しているのではないかと思った。
案の定、以下のようにするとtrueが返って来た。
issubclass([Hogeのインスタンス], (dynamodb_mapper.model_boto3.DynamoDBModel,))
実際、こんなフルパスで型指定をしないので旧DynamoDBModelは駆逐して新DynamoDBModelしかない状態にしておいたり、そもそもDynamoDBBoto3Model
みたいな名前にして今後開発を進めて行こうと思った。
関係ないがこの件について調べてみると、pythonのissubclassでハマるという記事があり、抽象クラスに対してはissubclass()は継承していてもfalseを返してくる、という豆知識も学んだ。 時間をかけた割には得たものが小さすぎるが、次へ進もう。
参考
takemasa5.tumblr.com【Laravel】TokenMismatchExceptionのエラーが出た
概要
LaravelをAPIサーバーとして利用したが、POST時にTokenMismatchException
と出てきたのでメモ。
対応方法
CSRFのチェックを外すためにapp\http\Middleware\VerifyCsrfToken.php
の中に以下を記載。
protected $except = [ 'api/*' ];
しかしこれはセキュアではないためしっかりとCSRFの対策をしなければいけない。 このWeb APIってCSRF対策出来てますか?って質問にこたえよう を読むとどういったAPIサーバにおけるCSRFの対策の仕方がわかる。
参考
https://stackoverflow.com/questions/37383165/tokenmismatchexception-for-api-in-laravel-5-2-31 https://qiita.com/rana_kualu/items/3f9d0d6b9a363fd2108e https://qiita.com/maruloop/items/e14d02299bd136f4b1fc
【Python】htmlファイルの改行とタブを削除するやつ
概要
htmlビルダーを利用して仕事をしているのだが複雑になってくると最終的に出力されるhtmlと、デザイナーが作ったこういう風に作ってください、というモックのhtmlとちゃんとあっているかを目で確認しないといけないのは非常に面倒である。Diffツールを使おうにも改行とかタブの数が若干違う、ということで差分として出されてしまうし、どうしようかと思った。 (もしかしてまともなエンジニアは何かツールを使っていたりする…?) でもまぁ、自分でミニマムに使えるので十分、というかんじなのでツールを探さずに話を進める。
出力されているhtmlの比較にはDiffツールを使うのだが、改行とかタブの数とかをいちいち直すのも手間なので、いっそhtmlタグごとに改行してタグの前方に着いているタブ(2スペや4スペ)を削除してから、Diffツールにかければ差分もまだ少なくなるかな、というのでpythonで作った。
<div> <ul> <li><span class="aaa">aaa</span></li> <li><span class="bbb">bbb</span></li> </ul> </div>
<div> <ul> <li> <span class="aaa"> aaa </span> </li> <li> <span class="bbb"> bbb </span> </li> </ul> </div>
以下がコードである。flatten.py
という名前ででも保存して、以下のように実行すると同じフォルダにテキストファイルが出力(ファイル名はもとのtxtファイルの先頭に_(アンダースコア)が付与された名前)されるので、htmlビルダーで出力した用とデザイナーが作った用で2回実行して出力された2ファイルをDiffにかければ使える。
python3 flatten.py hogehoge.txt python3 flatten.py fugafuga.txt
import sys import re argvs = sys.argv f = open(argvs[1]) file_contents = f.read() f.close() replaced_val = file_contents.replace(" ", "") replaced_val = re.sub(r'\t', "", replaced_val) replaced_val = re.sub(r'(<!--.*?>)', '', replaced_val) replaced_val = re.sub(r'(<.*?>)', r'\1\n', replaced_val) # \1はマッチした文字の再利用(※1) replaced_val = re.sub(r'(\n){2,10}', '\n', replaced_val) # 10である必要はないけど file = open('_' + argvs[1] + '.txt', 'w') file.write(replaced_val)
感想
すごく雑だけど、チェックしやすくなったー!
参考
【Typescript】[ts] Generators are only available when targeting ECMAScript 2015 or higher.がでた
redux-sagaを利用する際に、
export function* helloSaga() : void{ console.log("hello saga"); }
を書いたら、
[ts] Generators are only available when targeting ECMAScript 2015 or higher.
って言われた。
"target": "es6",
を書いてあげればOK。