投稿

7月, 2018の投稿を表示しています

【振り返り】2018年 4月~7月

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 大学院に入学して、あっという間に夏休みが近づいてきました。 このまま日々頑張って生きていくとあっという間に卒業してそうなので、一定期間ごとにふりかえりの記事でも書こうかと思いました。 技術系の記事や読書記録がメインで、あんまり日記的な記事は書かないのですが、大学院生活の実情を記したような記事は修士課程に進学を考えている学生の方などに少しは役に立つのでは、という考えもあります。 まああくまで個人的なログなので 「大学院生ってこんなことやってんだなー」ぐらいに思ってもらえればいいかとおもいます。 ## 4月 研究室をやめる 大学院に入学しました。 入学式はありましたがいきませんでした。まわりもあんまり出席してなさそうでした。 確かバイトに行った気がします笑 さて。とんでもないタイトルですが、本当です。 研究室に4月1日から所属して、教授と今後の研究計画を練ったり居室の自分の席を整備したりしていたのですが、所属して1週間後、教授のアカハラ(アカデミックハラスメント。まあパワハラの研究室版的なかんじです。)疑惑が浮上しました。 僕の中では教授が怒っている予兆のようなものは全く感じとれず、いきなり突き放すようなメールがきたのを覚えています。 アカハラの内容は簡単に説明すると、次のようなものでした。 僕の発言や態度が気に入らなかったようで、今後研究の面倒を見ないことや研究室のデータの使用許可を与えない、などの趣旨のメールをいくつかもらいました。 僕としては、放任主義の教授のもとで研究すること自体はウェルカムなのでそれ自体は問題なかったですが、この教授は自分の感情をコントロールできず職権を濫用してしまうタイプである可能性がある、という点でものすごく不安になりました。 何度か謝罪してみたものの、取りつく島もない様子で困り果ててしまい、結局学科の中で一番えらい教授の元へパワハラの証拠となるメールのスクリーンショットを見せたところ、他の研究室への移動を認めてもらうことができました。 このごたごたでいろいろあって、結局新しい研究室には5月から配属、ということになりました。 4月

ぼくのかんがえるさいきょうのFlaskアプリのディレクトリ構成

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 最初同じファイルにdbの設定、アプリの作成、モデル定義、ルーテイング、コントローラなどを詰め込んで書いてみて一応動いたから、次は機能ごとに分割してみることにした。 公式のディレクトリ構成を真似してこれにたどり着いた。 ``` - main -static(css,JS) -templates(html) -__init__.py(application,dbの初期化) -models.py(モデル) -views.py(ルーティング、コントローラ) -config.py(設定ファイル) -manage.py(アプリ実行用スクリプト) -requirements.txt(ライブラリ一覧) -instance(非公開設定ファイル置き場) ``` 内部の仕組みは次の通り。 1. mainの__init__.pyでapplicationとdbの初期化と設定の読み込み 1. このapplicationをviewsの__init__.pyで読んでルーティング 1. dbをmodelsで読み込んでモデル定義 1. ルーティングしたapplicationをmanage.pyで実行 この順にサンプルを載せていく。 まずapplicationとdbの初期化、設定の読み込み。 Flaskの設定については以下の記事も参考にしてみてください。 僕の考えるFlaskの設定まわりのベストプラクティス `config.py`に`Develop`クラスなど環境ごとに設定を定義する。 DBとの接続設定などをここに書く。 FlaskのDB連携については以下の記事を書いてます。 FlaskのDB連携(sqlite, SQLAlchemy)のやり方 ```python:main/__init__py from flask import Flask from flask_sqlalchemy import SQLAlchemy import os config = { "development": "config.Dev

FlaskのDB連携(sqlite, SQLAlchemy)のやり方

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 * sqlite * SQLAlchemy を使用した。 ORMとしてSQLAlchemyを使うと直にSQLを書かなくてすむのでよい。 ```python:app.py from flask_sqlalchemy import SQLAlchemy app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///"database_name".db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) ``` としてdbを通してDBにアクセスできる。 これによって`datebase_name`というDBを使用するようになる。 (sqliteではhogehoge.db的なファイルでデータベースが表現される) 実際にDBを作らないといけないので、ipythonとかでインタラクティブモードに入って ``` db.create_all() ``` とすると指定したDBファイルと、それを継承したモデルに紐付いたテーブルが作成される。 modelは以下のようにかく。 `db.Model`を継承したクラスを作ることでmodelを通してDBからデータを引っ張ってこれる。 ```python:app.py class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True) def __init__(self, username): self.username = username ``` データとってくるのはこんな感じ。 ``` User.query.all() ``` データを入れるときはこんな感じ ``` # hoge ユーザオブジェクトを作成 user = User(

僕の考えるFlaskの設定まわりのベストプラクティス

イメージ
Flaskの設定を扱う方法はいろいろある。 べたがきでもできるし、configファイルを作って読み込むこともできる。 調べた中で見つけたベストプラクティスをめも。 めっちゃ小規模のアプリとかでない限りはこれを基本にしていくといいのかも。 * 環境変数にdevelop とかproductionとか書いておく * configファイル側に各環境のオブジェクトへのマップを定義 * 環境変数で読み込んだ値をマップで飛ばして得られたオブジェクトをもとに設定する * githubにあげたくない設定はinstanceフォルダにおいておく 以下は`FLASK_APP_ENV`という環境変数を読み込んで設定している例。 環境変数が設定されていないと`production`を読み込むようにしている。 ローカル環境には環境変数に`develop`をセットしておくようにした。 ```python:example config_type = { "development": "config.Development", "testing": "config.Testing", "production": "config.Production" } app = Flask(__name__, instance_relative_config=True) app.config.from_object(config_type.get(os.getenv('FLASK_APP_ENV', 'production'))) app.config.from_pyfile('sensitive_data.cfg',silent=True) ``` ```python:config.py class Development(){ debug=hoge hoge=fuga } ``` `silent`ではinstance以下に指定した設定ファイルがない場合にエラーを出力するかを制御する。 Trueだとない場合もエラーは出さずにそのまま進めようとする。(が、seacret keyがない

Flaskのviewをblueprintで分割する

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 ルーティングの量が小さい場合は起動ファイルである`main.py`とかに書いてもいいし、少し大きくなってきたら`views.py`とかを作ってルーティング用のファイルを作ってもいい。 もっと多くなってきたらどうするか。`views.py`一枚ではルーティングが多すぎて編集したいメソッドが見当たらない!とか不満にかんじ始めたらblueprintの始めどき。 blueprintはviewを分割するのに役にたつ。 使い方はざっくりいうとこんな感じ。 1. viewsディレクトリをつくる 1. viewsディレクトリのしたにルーティングファイルをいくつか作る 1. 各ルーティングファイルでblueprintを作り、blueprintにルーティングを記述 1. viewsディレクトリに__init__.pyを作成 1. アプリオブジェクト(runする本体のやつ)に各blueprintを読み込んで設定する 各ルーティングファイルはどんな分け方でも大丈夫ぽいけど、モデルごとに作るのが良さそう。 各ルーティングファイルでblueprintを作るのはこんな感じ。 ```python:user.py from flask import Blueprint bp = Blueprint("user", __name__) @bp.routes.... #ルーティング ``` blueprintをアプリに登録するのはこんなかんじにやればできる。 ```python:__init__.py from flask import Flask from main.views import user, item from main import application modules_define = [user.bp, item.bp] for bp in modules_define: application.register_blueprint(app) ``` これでおっけい。一枚のファイルが小さくなって見やすくなりました。 あと。 こうするとurl

Flaskで1対多のモデルを定義する方法

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 `User`モデルに対して`Item`モデルが複数紐付いている例を載せておきます。 `User`はこんなかんじ。 `cascade="delete"`とすると親が削除された時に紐付いている子をすべて削除するようにできる。 ```python:models.py from main import db class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(100), default='', nullable=False) email = db.Column(db.String(100), unique=True, nullable=False) items = db.relationship("Item", backref="user", lazy="dynamic", cascade="delete") def __init__(self, username, email): self.username = username self.email = email ``` `Item`は以下。 ```python:models.py class Item(db.Model): __tablename__ = "items" id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False

さくらサーバーでmatplotlibを使おうとしたらエラーがでた

イメージ
こんにちは、ぐぐりら(<a href="https://twitter.com/guglilac">@guglilac</a>)です。 <a href="https://joppot.s3.amazonaws.com/wp-content/uploads/2014/01/python-logo.jpg" imageanchor="1" ><img border="0" src="https://joppot.s3.amazonaws.com/wp-content/uploads/2014/01/python-logo.jpg" width="320" height="151" data-original-width="403" data-original-height="190" /></a> ## 症状 ローカルでFlaskアプリの開発をして、一通り完成したのでさくらクラウドサーバーにあげて本番環境で動くか確認していた際、matplotlibが動かずにエラーが吐かれていた。 調べてみると、matplotlibの使用しているbackendを変更する必要があるとのことだった。 いろいろ探し回って解決したので、トラブルシューティングとしてまとめておく。 ## エラー ごちゃごちゃしていたからどのタイミングでこれらがでたのかわからなくなってしまった。 ほかにも違うエラー文が出てた気がする。 ``` RuntimeError: Invalid DISPLAY variable ``` ``` QXcbConnection: Could not connect to display ``` ## 解決方法 matplotlibをインストールする方法によって使用しているbackendが異なるみたいなので、ここをいじると上手く動いた。 使用しているbackendの確認方法、matplotlibの設定ファイルの場所の確認方法を載せておく。 どちらもpythonをインタラクティブモードで起動してコマンドを実行する。