第3回 オブジェクト指向設計実践ガイド 読書会 記録
前回に引き続き11名の参加者があり盛況でした。自分はお仕事の関係で途中参加しました。
今回は依存関係に関する話題。全体としては同意ですが、パラメータの順序への依存を切るためにハッシュオブジェクトに包むというのは同意できません。訳注にあるようにRuby(またはPython)では名前付き引数を使うのが良いと思います。 こんな感じ。
class Gear(object): def __init__(self, chainring, cog, wheel): self.chainring = chainring self.cog = cog self.wheel = wheel Gear(chainring=52, cog=11, wheel=Wheel.new(26, 1.5)).gear_inches
ハッシュに包むとIDEのコード補完の恩恵が受けられません。引数に何を指定して良いのか分からず、定義を参照せねばなりません。
ところで、参加者の中に学生さんが来ていました。聞けば文系の学部だそうですが、情報収集のためにPythonを使ってサイトのスクレイピングを試みているそうです。ぜひPython Boot Camp in 長野八ヶ岳に参加してほしいです。
彼を見ていると、ITエンジニア以外の方がやりたいことを実現するための仕掛けを自分で作る時代だなと痛切に感じます。
次回も楽しみです。
第2回 オブジェクト指向設計実践ガイド 読書会 記録
読書会常連の @tmtms さんが今回は不在でrubyを教えてくれる人がいなくて困ったな〜と思っていたら、rubyを知っている方が3人も来てくれてとっても助かりました。
外部からの参加者が5名、ギーラボ関係者が5名と最近になく賑やかな読書会になりました。全員がちょうど一度づつ読めたのも良かったです。 今回はrubyの文法についての質問が多めでしたが、rubyを知っている人にとってはrubyの文法理解に時間が多く取られるのはあまり良くないな〜と思いました。徐々に慣れるとは思うので、次回以降もrubyist諸氏におかれては今日に懲りずにご参加いただきたいです。
書籍内に出てくるコードはこちらで参照できます。 github.com
以下、普段pythonを書いている人間からの所感をいくつか。
getter/setterについて
attr_readerを使ってフィールドを隠蔽する、という話がありました。
pythonだとプロパティとフィールドのアクセス方法が同じなので、後からプロパティにもできます。
class Gear attr_reader :chainring, :cog def initialize(chainring, cog) @chainring = chainring @cog = cog end def ratio chainring / cog.to_f end end
は、プロパティを介さない場合は
class Gear(object): def __init__(self, chainring, cog): self.chainring = chainring self.cog = cog def ratio(self): return self.chainring / self.cog
となります。これをプロパティを介すように直すと
class Gear(object): _chainring = None _cog = None @property def chainring(self): return self._chainring @chainring.setter def chainring(self, value): self._chainring = value @property def cog(self): return self._cog @cog.setter def cog(self, value): self._cog = value def __init__(self, chainring, cog): self.chainring = chainring self.cog = cog def ratio(self): return self.chainring / self.cog
となる。う~ん、ちょっと記述量は多くなりますが、、、言いたいのはchainringおよびcogフィールドを使っている__init__
とratio
メソッドに変更が無いこと。なので後からプロパティ化することも割と手軽にできます。
配列操作について
def diameters wheels.collect {|wheel| diameter(wheel)} end
は、pythonだと普通は内包表記で書きます。
def diameters(self): return [diameter(wheel) for wheel in self.wheels]
ruby は最後に評価された値が戻り値になるそうです。これはこれで便利かも。
次回も楽しみです。
jinja2+WeasyPrintでお手軽印刷
過去にこんな記事を書いております。 koty.hatenablog.com この記事から4年近く過ぎた今でも印刷の需要はあります。ありますよね?
上記の記事はWPF(Windowsアプリ)ですがDjangoでPDFを出す機会があったのでメモ的に残します。
おおまかな方針としては、Jinja2でHTMLを生成→WeasyPrintでPDFに変換 という流れです。
自端末のPythonのバージョンは3.6です。
requirements.txtはこちら。
WeasyPrint==0.40 Jinja2==2.9.6 Django==1.11.5
この記事としては必須ではないのですが、templateを描画するbackendがJinja2になるようsettings.pyを変更します。
TEMPLATES = [ { 'BACKEND': 'django.template.backends.jinja2.Jinja2', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { }, }, ]
Jinja2に入力するhtmlのテンプレートはこちら。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{ title }}</title> <style> /* http://qiita.com/cognitom/items/d39d5f19054c8c8fd592 */ @page { size: A4; } </style> </head> <body> <h1>{{ title }}</h1> <div> <ul> {% for skil in skills %} <li>{{ skil }}</li> {% endfor %} </ul> </div> </body> </html>
viewはこちら。
from django.conf import settings from django.http import HttpResponse from jinja2 import Environment, FileSystemLoader from weasyprint import HTML def pdf_sample(request): # templateの読み込み template_dir = settings.TEMPLATES[0]['DIRS'][0] env = Environment(loader=FileSystemLoader(template_dir, encoding='utf8')) tpl = env.get_template('pdf_sample.html') # テンプレートにデータをbind html_str = tpl.render({ 'title':'私のスキル', 'skills': ('python', 'django', 'C#', 'WPF', '立ち泳ぎ'), }) # html文字列をPDFに変換 pdf_file = HTML(string=html_str).write_pdf() return HttpResponse(pdf_file, content_type='application/pdf')
あら簡単ですね!実際にはcssでいろんな調整が必要だろうと思います。この辺を参考に。 qiita.com
PythonでPDF印刷について調べるとReportLABとかがヒットします。これだとAPIがプリミティブ過ぎて使いづらいように思います。線を一本一本引いていくなんて辛すぎます。何らかの雛形を用意してそこにデータを突っ込む、ということをしたいわけです。それにはjinja2が最適です。
1ページだけの単票(死語か?)であればこの仕掛けで十分なように思います。 一方、改ページつきで各ページに共通なヘッダを出すといった帳票の場合は何か他の、例えばWPFとかを使う必要があるかもしれません。HTMLでもできるんかな??
本件のサンプルプロジェクトは以下です。 github.com
参考サイト:
- Welcome to Jinja2 — Jinja2 Documentation (2.9)
- WeasyPrint converts HTML/CSS documents to PDF - WeasyPrint
~短期集中講座~ 土日でわかるPythonプログラミング教室 環境づくりからWebアプリが動くまでの2日間コース (Informatics&IDEA)
- 作者: フロイデ株式会社吉谷愛
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2017/09/16
- メディア: 単行本
- この商品を含むブログを見る
- 作者: 池内孝啓,片柳薫子,岩尾エマはるか,@driller
- 出版社/メーカー: 技術評論社
- 発売日: 2017/09/09
- メディア: 大型本
- この商品を含むブログを見る
PyCon JP 2017 に参加してきた
参加された皆さま、スタッフの皆さま、お疲れさまでした。簡単ですが参加報告です。
ブースを出した
昨年からスポンサーをさせていただいていましたが、今年はブースも出しました。その辺の様子は以下をご覧ください。
私が転職してきてから数えても3回目の参加となり、だいぶ知り合いも増えてきました。そういった方々と立ち話しするだけでも楽しくすごせました。
セッションの所感
聴講セッション一覧
1日目
- プレゼンテーション:Industrial Test Automation with Asyncio | PyCon JP 2017 in TOKYO
- プレゼンテーション:Using machine learning to try and predict taxi availability | PyCon JP 2017 in TOKYO
- プレゼンテーション:Why you should do text analysis with Python (even if you don't want to) | PyCon JP 2017 in TOKYO
- プレゼンテーション:Building a Customized Personal Assistant with Python | PyCon JP 2017 in TOKYO
- プレゼンテーション:ドローンのフライトコントローラをPythonで制御してみた話 | PyCon JP 2017 in TOKYO
2日目
- プレゼンテーション:The theory of Serverless development by Python (理論から学ぶPythonによるサーバレス開発) | PyCon JP 2017 in TOKYO
- プレゼンテーション:Python におけるドメイン駆動設計(戦術面)の勘どころ | PyCon JP 2017 in TOKYO
- プレゼンテーション:Pythonの本気!RaspberryPiやEdisonを使ったIoTシステムの構築 | PyCon JP 2017 in TOKYO
- プレゼンテーション:Pythonをとりまく並行/非同期の話 | PyCon JP 2017 in TOKYO
- プレゼンテーション:SREエンジニアがJupyter+BigQueryでデータ分析基盤をDev&Opsする話 | PyCon JP 2017 in TOKYO
今年は英語のセッションを多めに聴講してみたのですが、正直言ってほとんど分かりませんでした。。。pyconに来るたびに英語力の無さを痛感します。*1その他に印象に残ったセッションについて所感を書きます。
プレゼンテーション:Industrial Test Automation with Asyncio | PyCon JP 2017 in TOKYO
- async awaitは実用できるっぽい。すくなくとも発表者の用途では
- pytestっていうテストのためのパッケージがあるらしい。unittestよりもイケてるらしい
- まとめでこんなようなことを言っていたと思う(英語なので自信なし
プレゼンテーション:Building a Customized Personal Assistant with Python | PyCon JP 2017 in TOKYO
フロントエンドにfacebook messenger、バックエンドに ChatterBotなるフレームワークを使ったという事例。面白そうだけど日本語の辞書がないっぽい。。
no japanese.. https://t.co/HYbHXi8SjS #pyconjp_201
— Kouichi Nishizawa(19 (@koty) 2017年9月8日
プレゼンテーション:ドローンのフライトコントローラをPythonで制御してみた話 | PyCon JP 2017 in TOKYO
大学の研究発表みたいだった。モーター動かせたって所までだったけど実際には制御系を作る必要があってその辺りの調整が難しかろうと思う。フライトコントローラーをOSSで作るという取り組みは素晴らしいです。
プレゼンテーション:The theory of Serverless development by Python (理論から学ぶPythonによるサーバレス開発) | PyCon JP 2017 in TOKYO
AWS Lambdaの話。質疑応答の時間が取られなかったので発表者に直接聞いた。
質問したこと1
— Kouichi Nishizawa(19 (@koty) 2017年9月9日
・cron実行だとAWS Lambdaが2回呼ばれることがあるが、api gateway経由の実行だと?
→ 内部構造を推測するに無さそうまたはかなり確立は低い(保証はない)
#pyconjp_202
補足をいただいた。質問したこと2
— Kouichi Nishizawa(19 (@koty) 2017年9月9日
・コネクションプールできるってことはサーバーレスといいつつデーモンあるよね?
→ある。コンテナと同じライフサイクルの何かしらのpythonプロセスがいる。#pyconjp_202
補足すると、厳密にはそもそもコンテナは隔離されたプロセスなので、コンテナ = プロセスでライフサイクルも当然同じです #pyconjp_202 https://t.co/gYOkul5lBk
— Masashi Terui (@marcy_terui) 2017年9月9日
質問したこと3
— Kouichi Nishizawa(19 (@koty) 2017年9月9日
・やっぱLambdaとRDBの相性って悪い?
→ENIの作成ペナルティもIAM認証によって解決できる。コネクションプールも可能。なのでこれまで言われているよりはハードルは下がっている。
#pyconjp_202
ということで参考になりました。 発表の中で「Web APIアプリケーションには別に向いてない」というような説明がありましたが、それだけそういった使われ方が多いんでは、ということを帰社後にお客さんと話していました。
Pythonを使う人の大多数はもはやプログラマーではないという、恐るべき現実を理解したのが今年の収穫 #pyconjp
— にしもつ (@24motz) 2017年9月9日
確かにこれは思った。
来年は少なくともプロポーザルは出したいなぁ。
drf_writable_nestedを試してみた
Django Restframeworkを使ってAPIを書くとコードの記述量が少なくて良いのですが、ネストしたオブジェクトの更新が煩雑になる点がちょっと不満です。ネストしたオブジェクトの更新をしようとすると途端に記述量が増えます。
実際、公式ドキュメントを見ると、
def create(self, validated_data): tracks_data = validated_data.pop('tracks') album = Album.objects.create(**validated_data) for track_data in tracks_data: Track.objects.create(album=album, **track_data) return album
とあります。ForeignKeyフィールドであるtracksをpopしてからcreateする必要があります。updateも同様。これはイマイチ。。。
と思っていた所以下のパッケージがあったので使ってみました。 github.com
確認コードはこちら。 簡単に動かしてみた限りでは便利そうです。
今回のコードはこちらに置いてあります。 https://github.com/koty/drf_writable_nested_sample
時間をみつけて、いろんなパターンを試してみたいと思います。
vue.jsを始めてみた
最近社内で突如としてSPA熱が高まっていて、勉強がてら作っている。
vue-cliでboilerplate的なものはできるので、そこからちょびちょびと機能追加していった。行の選択に応じて下部の詳細部分が書き換わる。reactiveで良い感じ。
Reactに取り組んでいる人がいて様子を見るにかなり苦戦している。慣れれば、あるいは大規模なシステムだと、Reactの方が効率が良いのかもしれない。だけど最初の入りやすさから自分はvueを選んだ。ちょっとかじっただけでもここまでできるのだからvueは最初のハードルは低いんじゃないだろうか。
この調子で、家業の伝票印刷システムのweb版を作りたい。どれくらいかかるか分からないけど。webpackの使い方とか全然分からないまま作っているけどとにかく動くものを作ることを優先する方が性に合う。
Django Background Tasksでお手軽バックグラウンド処理
バックグラウンドで動くバッチ処理を作りたい時にスケジューラを使うと思います。Pythonで代表的なタスクスケジューラはCeleryですかね。 でも、単に、長めの処理をキューイングしてシリアライザブルに実行していきたいといった簡単な要件だとちょっと大げさ過ぎるように感じ、他の仕掛けを探した所 Django Background Tasks というパッケージがあったの今回使ってみました。
基本的には、ドキュメントに書いてある通りですが。。
まずインストール。利用した時点でのバージョンは 1.1.0rc2
でした。django-background-task
(単数形)というパッケージも存在するのでご注意。今回紹介する複数形のは単数形のをforkしている模様です。
pip install django-background-tasks
settingsに設定を追記します。
INSTALLED_APPS = [
・・・
'background_task',
・・・
キューを保持するためのテーブルを作るので、migrateします。migrationファイルが含まれていないので、makemigrationsから。migrateすると、background_task
およびbackground_task_completedtask
というテーブルができます。
./manage.py makemigrations background_task ./manage.py migrate
タスクの定義。これだと、queue_name1というキューにキューイングし、5秒後に実行する、という設定です。
from background_task import background @background(queue='queue_name1', schedule=5) def some_long_duration_process(some_param1, some_param2): # 何か長い処理
タスクを呼び出す方の書き方です。普通にメソッドを呼んでいるように見えますが、実際にはキューイングされるだけでメソッドは呼び出されません。 @background
デコレータの内部でメソッド呼び出しが横取りされ、キューイングが行われます。background_taskテーブルを見ると分かるように引数はJSONにシリアライズされるので、確認はしていませんがJSONにシリアライズできる必要があると思われます。
# 登録側 some_long_duration_process('a', 'b')
説明の順番が若干前後しますが、予め以下のコマンドでバックグラウンドタスクを処理するプロセスを起動しておきます。
./manage.py process_tasks
サーバー構築時には、supervisordの下で動くようにしておきます。
[program:process_tasks] command=/.../bin/python ./manage.py process_tasks --settings=my_proj.settings.prod directory=/... user=centos autostart=true autorestart=true stdout_logfile=/.../...log ; 標準出力ログ stdout_logfile_maxbytes=1MB stdout_logfile_backups=5 stdout_capture_maxbytes=1MB redirect_stderr=true
そこそこ細かい設定もできるようですし、Celeryは大げさだなという場面では有効に使えると思いました。