Pipenvを使ってPython開発を快適に

最近、Pythonでコードを書く機会が増えてきました。

  • インデント強制
  • 標準ライブラリで出来ることが多い
  • Python3からは仮想環境であるvenvが標準で利用できる

などの理由で主に使っています。
ただ、Webアプリケーションなどでライブラリが必要な場面に遭遇すると、easy_installpipなどのツールを利用してパッケージを取得することがあります。
今回はこのパッケージマネージャについてです。

他言語のパッケージマネージャとの比較

メジャーな言語には、たいてい強力なパッケージ管理ツールがあります。
以下は有名ですね。

  • composer(PHP)
  • RubyGems(Ruby)
  • cpan(Perl)
  • npm、yarn(JavaScript)
  • Maven(Java)
  • NuGet(C#)

依存関係の解決だけでなく、設定ファイルを書くことで開発・本番での場合分けや
マルチプラットフォームでの環境の再現も容易に行うことができるものもあります。

ただ、先述したeasy_installpipでは、ここまで高度なことができません。
そこで、以下に続きます。

requirements.txt という選択肢

私は最近までこのやり方を使っていました。
Python3でvenvを使うやり方だと以下のような手順です。

ファイル名は何でも良いですが、一般的にこの名前が利用されているようです。
書き出したファイルには以下のように、ライブラリ名==インストールされたバージョンというフォーマットで記録されます。

インストール時は、読み込むrequirements.txtを指定してコマンドを実行します。

問題点

ざっと思いつくだけでも以下があります。

  • 環境ごとにrequirements.txtを分ける必要がある
  • ライブラリに変更があるたびにファイル再生成する手間がかかる
  • そもそもバージョンアップの手順が面倒(仮想環境でインストール→ファイル再作成)

Pipenv という選択肢

そこで登場するのがPipenvです。
パッケージ自体は1年前ぐらいからあったようです。
未検証ですが、ドキュメントを読む限りPython2でも利用できるようです(可能な限りPython3を使ってとのことですが)。

Pipenv: 人間のためのPython開発ワークフロー

詳細は上記をご覧いただくとして、ざっと使い方を。

requirements.txtがすでに存在するプロジェクトの場合、デフォルトで解析してくれます。
(ファイル名が異なる場合でも、-rオプションを使うことで読み込み可能です)
コマンド実行後、プロジェクトフォルダに以下2ファイルが生成されます。

  • Pipfile (toml形式)
  • Pipfile.lock (JSON形式)

他言語のパッケージマネージャを使ったことがある方は名前からだいたい想像がつくと思います。
Pipfileが設定ファイル、Pipfile.lockがインストールされたライブラリの情報です。
また、このタイミングで仮想環境も自動で作成してくれます。

Pipfileは以下のようなフォーマットです。

ただ、requirements.txtからのインポートだと、上記のようにバージョンが完全に固定されてしまっています。
なので、必要に応じてバージョンを変更します。

パッケージを追加でインストールする際には以下のようにします。

仮想環境で対象プログラムを実行するようなケースでも、Pipfileがあるディレクトリでpipenv runを利用することで実行可能です。

都度「あれ?仮想環境入ってたっけ…?」「今入っている仮想環境はどのプロジェクトや?」とならないのでとても便利です。
ちなみに、デフォルトだと仮想環境はホームディレクトリの.virtualenvsディレクトリ内に生成されるようです。
これをプロジェクト直下(=Pipfileと同じディレクトリ)にしたい場合、以下のように環境変数を定義してインストールしてください。

まとめ

複数人での開発だと、こういった機能は本当にありがたいですね。
待ち望んでいた機能なので、今後何らかの形で貢献できれば良いなと思っています。

Djangoを使ってデータベースを持たないAPI認証を行う

この記事は Django Advent Calendar 2017 20日目の記事です。

先日、満を持してバージョン2.0がリリースされました。
ただ、今回は新しい機能の紹介ではなく、1.xでも実装可能な「API認証」について書きます。

アジェンダ

  • この記事を書こうと思ったきっかけ
  • API認証の実装
  • まとめ

この記事を書こうと思ったきっかけ

以前、こちらにも書いたのですが、私は自分がつくったシステムのログイン~ログアウト処理に、これまた自分で作ったGo(Gin)のAPIを利用しています。
※最近はソーシャルログインなど外部サービスとの連携が楽にできるのですが、自分の勉強のためにこのようにしています。

で、以前ASP.NETでつくったレシピ管理ツールを今年Djangoに移行しまして、そこでもAPI認証をすることにしました。
CakePHP3やLaravelでは比較的簡単にできたのですが、Djangoは少し癖があったので、備忘も兼ねて書き残しておこうと思ったのがきっかけです。

API認証の実装

手順は大きく4つです。

  1. 認証用ユーザモデルの作成
  2. 認証ミドルウェアの作成
  3. 認証バックエンドの作成
  4. 設定ファイルの変更

通常、Djangoではマイグレーション時にauth_userテーブルが生成され、そこでユーザ情報を管理します。
グループやバーミッションなど細かい設定もできるのですが、今回はそれらは使用しません。

カスタムユーザモデルの作成

AbstratUserを継承した、独自ユーザーモデルを作成します。

セッションにsigned_cookieを利用しているためJSON変換処理を用意しています。

カスタム認証ミドルウェアの作成

django.contrib.auth.middleware.AuthenticationMiddlewareを参考に、以下のようなカスタムミドルウェアを作成します。

認証バックエンドの作成

Django標準の認証バックエンドとしてModelBackend(データベースを利用)やRemoteUserBackend(ヘッダのユーザー名を利用)が用意されていますが、
今回はAPI認証のため独自のバックエンドファイルを用意します。

設定ファイルの変更

最後に、settings.pyを修正します。

以上で実装完了です。

まとめ

Djangoには標準で管理画面がついてきますが、こちらはDBありきの実装なので、認証・認可をAPIで乗り切ろうと思うとかなり大変です。
標準の管理画面を利用する場合は嫌でもデータベースを使うことになるので、その場合は素直にテーブル管理しましょう。

一応、上記コード上にもコメントで記載していますが、結局のところ認証ユーザとauth_userテーブルを一旦同期させることになりそうです。

主な手順

  • ApiUserauth_userとして利用
  • API認証時、auth_userにレコードがなければ追加
  • リレーションの維持にはその値を利用

この実装を通して、Djangoが認証をどのように行っているかを学べたのは良い経験でした。
まだまだ知らない機能が多いので、これからも機能追加しつつ楽しんで開発出来たらと思います。

一部記事用に修正しましたが、今回利用したソースコードの元はこちらにありますので、良ければご覧ください。

AWSで心がぴょんぴょんするんじゃぁ^~

皆さん、パブリッククラウド使ってますか。
無料利用枠があるサービスもあるので、個人で使っているという方も多いのではないでしょうか。

かくいう私もその1人です。
今回はその中から、Amazon Web Services(AWS)を利用したサーバーレスアプリケーションの作成について紹介します。

今回利用したサービス

  • API Gateway
  • Lambda
  • DynamoDB

作成したもの

処理の流れ

  1. API Gatewayで作成したエンドポイントをクライアントがコール
  2. API GatewayがLamdba関数を実行
  3. Lamdba関数内でDynamoDBのデータを取得し、呼び出し元(API Gateway)へ返却
  4. API Gatewayがクライアントへデータを返却

手順

アカウント登録

何をするにもアカウント登録しなければ始まりません。
手順はこちらをご覧ください。

登録後12ヶ月の無料利用枠があり、この間はほとんどのサービスが無料で利用できます。
にもかかわらずクレジットカードを登録するというのはやっぱり気になるところではありますが、
従量課金という仕組み上(12ヶ月中であっても有料サービスを使えば課金が発生するため)やむを得ないのでしょうね。

なお、今回利用するリージョンはいずれも「ap-northeast-1」です。

IAM(Identity and Access Management)ユーザ登録

IAMは、ユーザに適切な権限を割り振って管理するための仕組みです。
今回は必須ではありませんが、登録時のルートアカウントを使い続けるのはセキュリティ的にお勧めされていないので、AWSを利用するなら作成しておいたほうが良いです(IAM自体は12ヶ月の無料利用枠後も無料で利用できます)。
「サービス」→「IAM」→「ユーザー」→「ユーザーの追加」で作成できます。
※ユーザーの作成およびポリシーの設定については本筋ではないので省略します。

テーブル作成(DynamoDB)

DynamoDBは、最近何かと話題のNoSQLデータベースです。
管理コンソールより「DynamoDB」→「テーブルの作成」でテーブルを作成します。
今回は以下のように定義しました。

  • テーブル名:categories
  • プライマリパーティションキー:category(文字列)
  • プライマリソートキー:sortOrder(数値)

NoSQLデータベースなのでキー以外は自由に設定できますが、今回はとりあえず「message(文字列)」というフィールドに表示したいメッセージを格納します。

関数作成(Lambda)

Lambdaは、指定したイベントが発生したときのみ動作する(=常時稼働しない)サービスです。
管理コンソールより「Lambda」→「関数の作成」→「一から作成」で作成します。
「カスタムロールの作成」を選択し、Lambda実行用のIAMロールを作成します。

なお、今回はこのIAMロールに「AmazonDynamoDBReadOnlyAccess」ポリシーを付与する必要があります。
管理コンソールより「IAM」→「ロール」→「上記で生成したロール名」を選択→「ポリシーのアタッチ」で上記をアタッチしてください。

言語は色々使えるのですが、今回はPython3.6を使いました。
以下のコードを入力し「保存してテスト」で関数をテストします。

Lambda関数が呼び出された際、まずlambda_handlerが実行されます。
引数eventにパラメータが格納されるので、それを利用してDynamoDBから値を取得します。

エンドポイント作成(API Gateway)

API Gatewayは、APIのエンドポイントを作成できるサービスです。
実際の処理は今回のようにLamdbaでも良いですし、他のAWSサービスでも良いです(もちろん、HTTPサービスもコールできます)。
管理コンソールより「Amazon API Gateway」→「APIの作成」を選択し、APIを作成します。
その後、実行するメソッドを追加します。

今回はデータを返却するだけなので「GET」のみ作成しました。
セットアップでは「統合タイプ」に「Lambda関数」を選択し、先ほど作成した関数のリージョンと名前を選択します。
なお、Lambdaにパラメータを渡すためには、統合リクエストを編集する必要があります。

「統合リクエスト」を選択し、「本文マッピングテンプレート」→「マッピングテンプレートの追加」で以下を入力して保存します。

最後に「アクション」から「APIのデプロイ」を選択し、ステージを決定のうえデプロイ完了です。
ステージエディターの「URLの呼び出し」横にあるURLが今回利用するエンドポイントです。

呼び出しは以下のようになります。

https://(エンドポイントURL)/(ステージ名)?category=(テーブルのcategory)&order=(テーブルのsortOrder)

できあがったもの

かなり駆け足、かつ途中端折っている部分もありますが、いかがでしたでしょうか。

所感

正直「こんなに簡単に実装できるのか」と衝撃でした。
IAMやLambda関数を利用したAPI認証も可能なので、モバイルサービスやSPAと連携したAPIも低コストで構築できるのではないでしょうか。
Lamdbaは常時稼働でない分、初回起動時の速度をいかに担保するかが重要に感じました。
今回の件と直接は関係ありませんが、IAMユーザはポリシー割り当てで結構ハマったので、そのあたりは次回以降に書きたいと思います。

ちなみに、これらの機能を使った別のアプリケーションをこちらに公開していますので、興味のある方はご覧ください。

Visual Studio CodeでDjangoをはじめる

以前書いたDjangoに関する記事の閲覧数が多いので、今回は私がDjangoアプリケーションを開発する際の設定について紹介します。

Pythonのインストール

こちら
今更2系を選ぶ理由は無いので、3系の最新をダウンロード・インストールしましょう。

Visual Studio Codeのインストール

PythonはVisual StudioやIntelliJなどのIDEでも開発可能ですが、設定が楽+軽量なので私はVisual Studio Codeを利用しています。
というわけで、まずはVisual Studio Codeをインストールしましょう。

プラグイン追加

Djangoの開発をするうえで必要な以下プラグインをVisual Studio Codeに追加します。

Jinjaについてはテンプレート用です(Djangoテンプレートでもハイライトが効くようになります)。
※Django template用のプラグインもあるのですが、これは.htmlの拡張子レベルで関連付けを行ってしまうため、通常のHTMLを書くときに影響が出ますので利用していません。

プロジェクトの作成

以前の記事を参考にしてください。

Python実行ファイルの定義

Pythonで開発するにあたり、ローカルにインストールしたPythonの実行パスを定義します。
「ファイル」→「基本設定」→「設定」または「エディタ左下の歯車」→「設定」でユーザー設定ファイルを開き、以下を定義してください。
※{path/to/〇〇} にはPythonまたは関連ライブラリがインストールされているディレクトリを定義してください。

実行設定の追加(launch.json)

Pythonに限らず、Visual Studio Codeで開いたプロジェクトを実行するために「F5」キーを押すと、実行する言語を選択するエリアが表示されます(必要に応じてここで対象言語用のプラグインをインストールすることができます)。
ここで言語を選ぶと、Visual Studio Codeでは関連する実行設定ファイル(launch.json)を「プロジェクトルート/.vscode」に自動で生成してくれます。
このファイルにある「Django」の箇所を必要に応じてメンテナンスします(以下は例ですが、初期設定から基本的には変更不要です)。

${config:python.pythonPath}は先ほど設定したpythonPath、${workspaceRoot}は現在Visual Studio Codeで開いているプロジェクトのルートディレクトリを示しています。

実行

エディタ左側の虫マークを選択し、「デバッグ」という表示横のプルダウンから「Django」を選び、横向き三角ボタンを押せば実行されます。
ちなみに、上記設定でデバッグ可能なので、ブレークポイントを貼るとそこで止められますし、変数の中身も確認できます。
ただし、それらは「–noreload」が無ければできません。

なので、通常の「ファイル変更」→「リロード」という手順を踏む場合は、上記設定から「–noreload」を除外して実行することになります(この場合、エディタのデバッグコンソールにも何も出力されません)。
eclipseやIntelliJでも同様のようです。

なお、私個人が作っているものがこちらにありますので、Djangoでの開発に興味のある方は是非ご覧ください。
※PRも受け付けております。

Djangoの記事は需要がありそうなので、またそのうち書きます。

Djangoを利用してアプリを作る

以前も少し書きましたが、C#とASP.NETで作成していた自分用の「レシピ管理システム」を、現在Djangoで作り直しています。
※リポジトリはこちら

DjangoはPythonで作られたフルスタックフレームワークです。
よく言語比較をされるRubyではRuby on Railsが有名であり、そちらのほうが巷では人気がありますが、
昨今の機械学習ブームも手伝ってPythonという言語自体はとても注目されています。

以前バッチ処理でPythonを利用していた私としては、せっかくなのでWebアプリも作ってみようということで挑戦することにしました。
ただ、Djangoに関する文献やドキュメントは英語が多く、最低限動作させるのにも結構苦労しましたので、今後Djangoを学ぶ方の役に立てばいいなと思いこの記事を書きます。

ちなみにチュートリアルは基本日本語ページですが、半分ぐらいは英語ページのままだったりします。

プロジェクト≠アプリケーション

他言語でWebフレームワーク利用経験があると、まずここで混乱します(私もそうでした)。

たとえば「CakePHP」の場合、以下コマンドでアプリケーションを作成して、それをそのままプロジェクトとして利用します。

先ほどあげた「Ruby on Rails」も同様です。

Djangoの場合、プロジェクト内で機能や用途に応じてアプリを分けるという方針で開発することになります。
最近のソーシャルゲームだと、ユーザ情報、イベント情報、手持ちのキャラクターなどはすべて別アプリで、それらをまとめて1つのプロジェクトとして管理するようです。
※ここらへんは、作成中のレシピ管理システムにはまだ反映できていません…。

プロジェクト作成

アプリ作成

利用する主なファイル

他のフレームワークであるような「MVC構成」とは少し異なります。
作成したアプリで以下のファイルが配置されますので、それぞれの中で一括管理するようです。

  • urls.py…ルーティング関連
  • views.py…コントローラ関連
  • models.py…モデル関連

urls.pyは、デフォルトではプロジェクト・各アプリそれぞれにあります。
プロジェクトのurls.pyでは各アプリへの振り分けを行い、各アプリではそれ以下のパスの振り分けを行っています。

以上、ひとまず基本部分でした。
テンプレートでのヘルパー利用やモデルの設定についても触れたいのですが、それは次回以降にまわします。
興味を持っていただけた方は、まずは冒頭のリポジトリをご覧ください。

サービスはリリースしてからが勝負

以前、健康診断で引っかかったことをきっかけに、自分用にレシピをまとめるサイトを作成しました。
その当時興味があったASP.NET(C#)で作成したのですが、サーバとして利用しているUbuntuへのデプロイが面倒だったこともあり(当時はMonoもそこまでメジャーじゃなかったので)、あまりメンテナンスできておりませんでした。

そして最近、これをPythonで書き直そうとしています。
Pythonは以前からバッチ処理で利用していたのですが、Webフレームワークとして利用してみたかったということと、今後様々な分野で活かせそうだという期待を込めて本格的に学習することに決めました。

フレームワークには一番メジャーなDjangoを使っているのですが、日本語のドキュメントがほとんどないのでかなり大変です。
困ったときは以下のリファレンスを参照するようにしています(日本語用のページですが、英語のままの部分も多いです)。
Django ドキュメント

1つのプロジェクトに複数のアプリがぶら下がるという構成にはまだ慣れないですが、フルスタックフレームワークということもあり開発は比較的スムーズに進んでいます。
まずは3月中に運用開始できることを目標にしています。

次回はこのDjangoを使った基本的な開発について触れようと思います。