Flutter 初めてのアプリ作成 ストップウォッチ
今回はFlutterで簡単なストップウォッチを作成してみました。
環境
- OS : Windous10
- Flutter : v2.2.3
完成品
0秒からではなく、どの時間からでも開始できるストップウォッチにしてみました。
ストップウォッチを使っていて、途中から始めたい事がよくあったので、、、
機能は3つです。
1. 開始時間設定
2. ストップウォッチ開始、停止
3. リセット
Flutter習得
習得にはKBOYさんが運営しているFlutter大学の動画を見させていただきました。
環境構築から、簡単なYoutube風アプリ(側だけ)の作成まで、動画を見ながら2日で実施出来ました。
※2020年の動画で少し古いですが動作しました。
- 環境構築 : https://www.youtube.com/playlist?list=PLuLRJz1UnJzE4-HlkLTG8ARbZ2TDBNHzZ
- Flutter基礎 : https://www.youtube.com/playlist?list=PLuLRJz1UnJzEDjRr1XkqyOzFzUi3Df4B0
ストップウォッチ作成
1日でサクッと作成しました。
FlutterPicker というプラグインを使用すると、時間設定が楽に作成できます。
タイマー部分は、Timerで1秒の定期実行でカウントアップの関数を呼び出しています。
画面の更新は、SetStateではなくProviderパッケージを使い、notifyListeners()
で変更を通知しています。
Widgetのツリー
ソースコード
/* main.dart メイン画面 */ import 'package:flutter/material.dart'; import 'package:flutter_picker/Picker.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'main_model.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'ストップウォッチ', home: ChangeNotifierProvider<MainModel>( create: (context) => MainModel(), child: Scaffold( appBar: AppBar( title: Text('ストップウォッチ'), ), body: Consumer<MainModel>( builder: (context, model, child) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextButton( // タイマー時間表示 + Editボタン onPressed: () { if (!model.isEditTimeEnabled) return; // 時間設定ウインド表示 Picker( adapter: DateTimePickerAdapter( type: PickerDateTimeType.kHMS, value: model.timerTime, customColumnType: [3, 4, 5], ), title: Text("Select Time"), onConfirm: (Picker, List values) { model.changeTimerTime(DateTime.utc( 0, 0, 0, values[0], values[1], values[2])); }, ).showModal(context); }, child: Text(DateFormat.Hms().format(model.timerTime), style: TextStyle( fontSize: 80, )), ), Row( // START,STOP,RESETボタン mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( // STARTボタン padding: const EdgeInsets.all(8.0), child: ElevatedButton.icon( onPressed: !model.isStartEnabled ? null : () { model.startTimer(); }, icon: Icon(Icons.play_arrow), label: Text('START')), ), Padding( // STOPボタン padding: const EdgeInsets.all(8.0), child: ElevatedButton.icon( onPressed: !model.isStopEnabled ? null : () { model.stopTimer(); }, icon: Icon(Icons.stop), label: Text('STOP')), ), Padding( // RESETボタン padding: const EdgeInsets.all(8.0), child: ElevatedButton.icon( onPressed: !model.isResetEnabled ? null : () { model.resetTimerTime(); }, icon: Icon(Icons.clear), label: Text('RESET')), ) ], ), ], ), ); }, ), ), ), ); } }
/* main_model.dart メイン画面のデータモデル */ import 'dart:async'; import 'package:flutter/material.dart'; class MainModel extends ChangeNotifier { Timer? timer; DateTime timerTime = DateTime(0); bool isStartEnabled = true; bool isStopEnabled = false; bool isResetEnabled = true; bool isEditTimeEnabled = true; // 開始時間変更 void changeTimerTime(DateTime time) { timerTime = time; notifyListeners(); } // 開始時間リセット void resetTimerTime() { timerTime = new DateTime(0); notifyListeners(); } // ストップウォッチ開始 void startTimer() { if (timer == null) { timer = Timer.periodic(Duration(seconds: 1), (timer) { countUpTime(1); }); } isStartEnabled = false; isStopEnabled = true; isResetEnabled = false; isEditTimeEnabled = false; notifyListeners(); } // ストップウォッチ停止 void stopTimer() { timer!.cancel(); timer = null; notifyListeners(); isStartEnabled = true; isStopEnabled = false; isResetEnabled = true; isEditTimeEnabled = true; notifyListeners(); } // 1s カウントアップ void countUpTime(int second) { timerTime = timerTime.add(Duration(seconds: second)); notifyListeners(); } }
参考
- Flutter大学 : Flutter大学 - YouTube
- FlutterPicker を使う : https://rinoguchi.net/2021/05/flutter-hour-minute-second-input.html
React公式チュートリアル 三目並べ 応用課題
Reactの公式チュートリアルにある三目並べゲーム (tic-tac-toe)を作ってみました。 ゲーム自体は記事の通りに進めれば完成できるので、最後の応用にあった6つの課題を追加実装しています。
応用課題
- 履歴内のそれぞれの着手の位置を (col, row) というフォーマットで表示する。
- 着手履歴のリスト中で現在選択されているアイテムを太字にする。
- Board でマス目を並べる部分を、ハードコーディングではなく 2 つのループを使用するように書き換える。
- 着手履歴のリストを昇順・降順いずれでも並べかえられるよう、トグルボタンを追加する。
- どちらかが勝利した際に、勝利につながった 3 つのマス目をハイライトする。
- どちらも勝利しなかった場合、結果が引き分けになったというメッセージを表示する。
出来たもの
全ての応用課題を実装したものになります。
pythonでLoggingを使ってみる
実行環境
- OS : Windows10
- Python : v3.9.6
Loggingについて
Pythonを入れると標準で入ってくるモジュールです。
logging --- Python 用ロギング機能 — Python 3.9.4 ドキュメント
import logging
セットアップ
loggingインスタンスの生成
直接インスタンス化するのではなく、getLogger(name)
を介してインスタンス化する事が推奨されています。
logger = logging.getLogger("hogehoge")
logger = logging.getLogger(__name__)
インスタンスの親子
親インスタンスから子を作成。
# 親インスタンス parentLogger = logging.getLogger(__name__) # 子インスタンス childLogger = logging.getLogger(__name__).getChild("hogehoge")
ログレベルの設定
ログを出力する閾値を設定する。
閾値を設定することで、それ以上深刻なログのみ出力される。
ロガーインスタンス初期値 : NOTSET
ルートロガー初期値 : WARNING
レベル | 数値 |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 |
INFO | 20 |
DEBUG | 10 |
NOTSET | 0 |
# レベル定数 CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 # Debugレベルに設定 logger.setLevel(logging.DEBUG) logger.setLevel(10) # ルートロガー初期値確認 logger = logging.getLogger() logger.getEffectiveLevel() # -> 30
ログ出力
レベルごとにメソッドを使い分けて出力する。
# 各レベルで出力 logger.debug("debug") logger.info("info") logger.warnig("warning") logger.error("error") logger.critical("critical") # 変数を出力文字内に入れる name = "hogehoge" logger.debug("Name:%s", name) # -> Name:hogehoge
NOTSETについて
初期値のNOTSET
レベルは、
ロガーがルートロガーであれば処理される、そうでなくてロガーが非ルートロガーの場合には親ロガーに委譲させる という設定で、NOTSET以外の設定を見つけるまで祖先をたどる。
ルートロガーの初期はWARNING
で設定されているため、レベル設定を行わない場合、WARNING以上しか出力されない。 引用元: Logging HOWTO — Python 3.9.4 ドキュメント
# warning以上しか出力されない logger = logging.getLogger(__name__) logger.info("info") -> logger.warning("warning") # -> warning # ルートロガーのレベル設定 logging.basicConfig(level=logging.DEBUG)
basicConfigでは、ほかにフォーマットや、ハンドラなどで基本的なロギングの設定を行える
Handler
ログの送り先をハンドラとして設定する
StreamHandler
標準出力(stdout)、標準エラー出力(stderror)へ送信する
# ロガーインスタンス作成 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # Handler作成 sh = logging.StreamHandler() sh.setLevel(logging.INFO) # loggerにHandler追加 logger.addHandler(ch) logger.info("hogehoge") # -> hogehoge
FileHandler
ログ出力をファイルに送信する
# ロガーインスタンス作成 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # # Handler作成 出力ファイル名_LOGFILE.log fh = logging.FileHandler("./LOGFILE.log") fh.setLevel(logging.INFO) logger.addHandler(fh) logger.info("hogehoge") # ==LOGFILE.log== hogehoge
Formatter
表示するメッセージの書式を設定する
フォーマット文字列内に特別な文字列を配置することで、日付やログレベルなどをメッセージに含められる。
フォーマッタの初期値は%(message)s
のみで、メッセージだけが出力される
出力される内容 | |
---|---|
%(asctime)s | 日時 |
%(name)s | ロガーインスタンス名 |
%(levelname)s | ログレベル |
%(message)s | メッセージ |
# ロガーインスタンス作成 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # Handler作成 ch = logging.StreamHandler() ch.setLevel(logging.INFO) # Formatter作成・追加 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') ch.setFormatter(formatter) # loggerにHandler追加 logger.addHandler(ch) logger.info("hogehoge") # -> 2021-07-18 00:00:00,000 - __main__ - INFO - hogehoge logger.warning("hogehoge") # -> 2021-07-18 00:00:00,000 - __main__ - WARNING - hogehoge logger.error("hogehoge") # -> 2021-07-18 00:00:00,000 - __main__ - ERROR - hogehoge logger.critical("hogehoge") # -> 2021-07-18 00:00:00,000 - __main__ - CRITICAL - hogehoge
設定ファイルよりセットアップ
いままでの設定はコード内で行っていたが、
設定ファイル(.conf)を事前に定義して読み込みを行う事もできる。
# ==logging.conf== # logger keys "root" [loggers] keys=root # handler keys "streamHandler","fileHandler" [handlers] keys=streamHandler,fileHandler # formatter keys "formatter" [formatters] keys=formatter # "root" logger setup [logger_root] level=DEBUG handlers=streamHandler,fileHandler # "streamHandler" handler setup [handler_streamHandler] class=StreamHandler level=DEBUG formatter=formatter # "fileHandler" handler setup [handler_fileHandler] class=FileHandler level=DEBUG formatter=formatter args=('LOGFILE.log', 'w') # "formatter" formatter setup [formatter_formatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
# conf読み込み logging.config.fileConfig("./logging.conf") # loggerインスタンス生成 logger = logging.getLogger(__name__)
辞書型で定義してセットアップ
コード内で辞書型で定義することもできる。
設定内容は設定ファイルでの設定と同じ。
# 辞書型で設定内容を作成 logging_conf = { 'version': 1, 'formatters': { 'formatter': { 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s' }, }, 'handlers': { 'streamHandler': { 'level':'DEBUG', 'class':'logging.StreamHandler', 'formatter': 'formatter' }, 'fileHandler':{ 'level':'DEBUG', 'class':'logging.FileHandler', 'formatter': 'formatter', 'filename': 'LOGFILE.log', 'mode': 'w' }, }, 'loggers': { 'root': { 'handlers': ['streamHandler', 'fileHandler'], 'level': 'DEBUG', } } } # 辞書型で読み込み logging.config.dictConfig(logging_conf) # インスタンス作成 logger = logging.getLogger(__name__)
Pythonで flake8 (Linter,Formatter) を使ってみる
今回は、Linter Formatterについてそろそろ知っときたいなと思い調べたのでメモ
実際の動作に関係するものではないので、後回ししてました、、
Lintter, Formatter
Linter ってなに
lintとは、コンピュータプログラムなどのソースコードを読み込んで内容を分析し、問題点を指摘してくれる静的解析ツール。また、そのようなツールで解析を行うこと。ツールを指す場合は “linter” (リンター)と呼ぶこともある。
引用元 : IT用語辞典 e-Words
- プログラムを実行する前に、問題が発生しそうな箇所を指摘してくれるもの。(変数を宣言してるのに使ってないなど)
- 解析するプログラムを"リント"、解析ツールを"リンター"と呼ぶ。
Formatter ってなに
定めたルールに従ってコードをチェック・成形するツール。
動作に影響しないコードスタイルについてチームで統一することで、コードを読みやすくするもの。
よくあるルールとしては、空白の入れ方や改行位置などがあるそうです。
flake8
flake8ってなに
Flake8 is a wrapper around these tools: ・ PyFlakes
・ pycodestyle
・ Ned Batchelder’s McCabe script
引用元: flake8 · PyPI
- PyFlakes : コード規約PEP8に準じ、コードのエラーチェックをするもの。 Lintter
- pycodestyle : コード規約PEP8に準じ、コードスタイルをチェックするもの。 Formatter
- Ned Batchelder’s McCabe script : 複雑度チェッカー
個別で存在するのLinter , Formatterをまとめて使えるものまとめて使用できるものだそうです。
インストール
pip install flake8
実行コマンド
$ flake8 [ファイル or ディレクトリ] $ flake8 ./main.py (ファイル) $ flake8 ./MyProject (ディレクトリ)
使用例
参考に簡単なコードにflake8を実行してみます。
# == main.py == def add(a,b): return a+b if __name__ == "__main__": a = 1 b = 2 sum = add(a,b) print(sum)
# 実行結果 $ python main.py 3
flake8の実行
$ flake8 main.py main.py:3:10: E231 missing whitespace after ',' main.py:6:1: E305 expected 2 blank lines after class or function definition, found 1 main.py:9:16: E231 missing whitespace after ',' main.py:10:15: W292 no newline at end of file
4つエラーが出ました。
E○○ W○○ とコードが出るのが、チェックしている項目ごとのコードになります。
ErrorCodes
今回出ているエラーとしては以下のようです。
- E231 : [ , ; : ]の後に空白がありません
- E305 : 関数またはクラスの終了後に2行の空白行が必要です
- W292 : ファイルの終わりに改行がありません
特定のエラーのみチェックしたい・省略したい場合はオプションで設定できます。
# 特定のエラーのみチェック $ flake8 --select E231,E305 main.py # 特定のエラーを省く $ flake8--ignore E231,E305 main.pu
構成ファイルの作成
実行時に毎回オプションを設定して、エラー項目を設定するのは大変なので、、、
flake8の構成ファイルを使って読み込めるようにしてみます。
構成ファイルの書き方
flake8コマンドのオプションで設定できる内容を並べていくしていくようです。
参考に、公式ドキュメントで使用されていたものです
configuration
# == .flake8 == [flake8] ignore = D203 exclude = .git,__pycache__,docs/source/conf.py,old,build,dist max-complexity = 10
設定されている内容
自動生成でチェックの必要がないファイルなどは、事前に設定していてもよいかもしれません。
ユーザごとの設定
構成ファイルを保存しておけば自動的に読み込まれるようです。
OS保存先はOSごとに設定ファイルの保存場所
とファイル名
が違っています。
Windows : ~\.flake8 Linux : ~/.config/flake8
チーム内で共有
各々が作った構成ファイルを使用すると、コードが統一されず読みづらいです。 なので、事前に構成ファイルをgitプロジェクト内に含め共有し、それを使ってflake8を実行すると良いと思います。
# --config オプションを使って、構成ファイルを指定 $ flake8 --config flake8 main.go
最後に
導入が意外と簡単に出来るので、面倒ですがプロジェクトと開始時にやっておくとコードが統一されて良さそう。
SwaggerEditorでAIPを設計してみる
SwaggerEditorを使ってAPIの設計を行ったのでメモ
この記事で行っていること
- Swaggerとは
- OpenAPIとは
- Swager Editorを使ってみる
- Swagger Codegenでコード生成
- FlaskAPIServer 起動
- SwaggerUIでリクエストお試し
- SwaggerEditorを使ってみて
Swaggerとは
API開発をする際に使えるツールが詰まったもの。 以下のツールがオープンソースで誰でも使える
ツール | |
---|---|
Swagger Codegen | OpenAPIの定義からサーバ、クライアントのコードを生成する |
Swagger Editor | OpenAPIの仕様で、APIを設計するエディタ |
Swagger UI | 設計したAPIを表示するビュワー。実際にリクエストを送り、応答を確認できる。 |
OpenAPIとは
- OpenAPI Initiative(OAI)というコミュニティが定めた、API仕様を記述する標準フォーマット
- JSON、YAMLの二つの形式で表すことが可能
- ファイル名デフォルトは
openapi.json
かopenapi.yaml
用語の整理
- OAI = OpenAPI Initiative というコミュニティ、団体
- OAS = OpenAPI Specification OpenAPIの仕様
- swagger2.0 = v2.0のOASフォーマット
- OAS3.0 = v3.0のOASフォーマット
Swager Editorを使ってみる
書き方はこちらを参考に、 簡単なAPIを設計
OpenAPIで定義できる項目が多くて大変💦💦
今回設計するAPI
- BaseURL : http://localhsot:5000/api/v1
- Version : 0.0.1
エンドポイント一覧
メソッド | パス | |
---|---|---|
GET | /users | すべてのユーザ情報を取得 |
GET | /users/{id} | 指定idのユーザ情報を取得 |
POST | /users | 新規のユーザを登録 |
openapi.yaml
openapi: 3.0.0 info: title: "初めてのSwaggerEditor" description: "初めてSwaggerEditorを使って、API設計してみる" termsOfService: "" version: "0.0.1" servers: - url: "http://localhost:8080/api/v1" description: "ユーザ情報を取得するAPIサーバ" paths: /users: summary: "Get Users" description: "Usersに関する操作" get: summary: "Get Users" description: "全てのユーザを取得します" responses: 200: description: "全てのユーザを返す" content: application/json: schema: type: string examples: users: value: [{ "id":1, "name":"Jon", "age":19 },{ "id":2, "name":"Mike", "age":21 }] post: summary: "Add User" description: "新しいユーザを追加します" operationId: "addUser" requestBody: required: true content: application/x-www-form-urlencoded: schema: properties: name: description: "ユーザの名前" type: string age: description: "ユーザの年齢" type: integer required: - "name" - "age" responses: 201: description: "正常にユーザを追加しました" 400: description: "不正なリクエストです" /users/{user_id}: parameters: - name: "user_id" in: path required: true description: "userId" schema: type: integer get: summary: "Get One User" description: "1人のユーザを取得します" responses: 200: description: "1人のユーザを返す" content: application/json: schema: type: string examples: user: value: {"id":1,"name":"Jon","age":19}
Swagger Codegenでコード生成
今回は、Python Flask でコードを生成してみる
タブからの[Generate Server]⇒[python-flask] を選択
生成されたファイル
選択していないが、Python3.6
で作成された
コードはAPIサーバの基本部分のみなので、実際に使用する場合はcontroller.py などに追加する必要がある
swagger_server │ .dockerignore │ .gitignore │ .swagger-codegen-ignore │ .travis.yml │ Dockerfile │ git_push.sh │ README.md │ requirements.txt │ setup.py │ test-requirements.txt │ tox.ini │ ├─.swagger-codegen │ VERSION │ └─swagger_server │ encoder.py │ type_util.py │ util.py │ __init__.py │ __main__.py │ ├─controllers │ authorization_controller.py │ default_controller.py │ __init__.py │ ├─models │ base_model_.py │ users_body.py │ __init__.py │ ├─swagger │ swagger.yaml │ └─test test_default_controller.py __init__.py
FlaskAPIServer 起動
Dockerfileも生成されたので、それで起動してみる
SwaggerUIよりリクエストを送信してみたら、CORSエラーが返ってきた
CORSについてか解決できなかったので、docker-composeでSwaggerEditor
とFlaskAPIServer
を同時に起動。Nginx
をプロキシサーバとして動かすことで、ドメインを統一してエラー回避
## ファイル構成 {Project} |- docker-compose.yaml |- nginx.conf └─ swagger_server # SwaggerEditor より生成したコード
## docker-compose.yaml version: "3.8" services: nginx: image: nginx ports: - 8080:8080 volumes: - ./nginx.conf:/etc/nginx/conf.d/nginx.conf swagger_editor: image: swaggerapi/swagger-editor flask_api_server: build: context: ./python-flask-server-generated dockerfile: Dockerfile
## nginx.conf server { listen 8080; # SwaggerEfitor location / { proxy_pass http://swagger_editor:8080; } # Flask API Server location ^~ /api/v1 { proxy_pass http://flask_api_server:8080/api/v1; } }
SwaggerUIでリクエストお試し
起動したAPIサーバに対して、SwaggerUIからリクエストを送ってみると、do some magic!
とレスポンスが返ってくることを確認
SwaggerEditorを使ってみて
- API設計とドキュメント作成(Swagger UI)が同時に出来て楽
- SwaggerEditorでは、SwaggerUIがホットリロードしてくれるので書き易い
- OASで定義できる項目が多いので、前提としてAPI設計について知っておく必要がある
- 生成されたコードから編集するのみでAPIサーバを構築できるので楽
今回は以上です。
GitLab Privateリポジトリより go get してみる
自分が作成したGitLabリポジトリより go get する方法をメモ
実行環境
- Windows 10 Pro
- GO 1.15.6
GitLabリポジトリ作成
- https://gitlab.com/へログインし、プロジェクトを作成
- Visiblity Level を [Private]に設定
- 今回は、ProjectName を "go-package"とする
今回go get する自作パッケージを配置
- リポジトリよりクローン
go mod init XXXX
でgo.mod を生成- mathディレクトリ内に、自作"math"パッケージを作成
- mathパッケージは平均を返す関数"Average"のみ実装
$ git clone https://gitlab.com/xxxxxx/go-package.git $ cd go-package.git $ go mod init gitlab.com/xxxxx/go-package # 自分のリポジトリに合わせて編集する
# /go-package/go.mod module gitlab.com/xxxxx/go-package go 1.15
# /go-package/math/math.go package math // Average 平均値を返す func Average(s []int) int { total := 0 for _, v := range s { total += v } return int(total / len(s)) }
# ディレクトリ構成 go-package │ go.mod └─math └─math.go
AccessToken作成
- リポジトリへアクセスするためのトークンを作成 参考:https://capibara1969.com/55/
read_api
とread_repository
権限を付けて発行- 発行されたトークンは一度しか表示されないので、忘れないようメモ
go get でインストール
確認のため適当なプロジェクト作成
$ mkdir goproject $ cd goproject $ go mod init main
AccessToken登録
~/.netrc
を作成GITLAB_USERNAME
: GitLabにログインしているユーザ名ACCESS_TOKEN
: 先ほど作成したAccessToken
# ~/.netrc machine gitlab.com login GITLAB_USERNAME@gitlab.com password ACCESS_TOKEN
環境変数 設定
$ set GOPRIATE=gitlab.com/xxxxxx/go-package
いざ、go get
- イントールされたファイルは、
$GOPATH\pkg\mod\gitlab.com\xxxxxx\go-package@v0.0.0
に配置される
$ go get gitlab.com/xxxxx/go-package
# /goproject/go.mod module main go 1.15 require gitlab.com/xxxxxx/go-package v0.0.0 // indirect
プロジェクトへインポート
- 適当なgoファイル
main.go
を作成し、自作パッケージをインポート math/Average
関数を実行し、平均値計算結果が出力される
# main.go package main import ( "fmt" // インポート "gitlab.com/xxxxxx/go-package/math" ) func main() { fmt.Println(math.Average([]int{1, 2, 3})) }
# 結果 2
GOPRIVATE
を設定しなかった場合
503 Service Unavailable
エラーが返ってくる
go get gitlab.com/xxxxxx/go-package: unrecognized import path "gitlab.com/xxxxxx": reading https://gitlab.com/xxxxxx?go-get=1: 503 Service Unavailable
pipenv + Flask 簡単なwebアプリケーション作成
最近初めてpipenvを使い仮想環境とパッケージ管理を行えることを知ったので、メモ。
pipenvとは
仮想環境作成(venv)とパッケージ管理(pip)が合わさったもの
実行環境
- Windows10 Pro
- python 3.9.6
準備
pipenvインストール
pipコマンドでインストール
pip install --upgrade pip # pipアップグレード(必要に応じて) pip install pipenv
プロジェクトファイル作成
mkdir project cd project
仮想環境作成
使用するpythonバージョンに応じて選択(選択したバージョンのpythonがインストールされていること)
実行すると、~/.virtualenvs/project-XXXXXX
に仮想環境が作成され、プロジェクト内にPipfile
が作成される
# 仮想環境作成 pipenv --three # python3で作成 pipenv --two # python2で作成 pipenv --python 3.8 # バージョンを指定して作成
# project\Pipfile [[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] [dev-packages] [requires] python_version = "3.9"
作成する場所を変更する場合
たとえば以下のように変更したい場合、それぞれ環境変数を設定
仮想環境を作成するディレクトリを変えたい
# .\venv\project-XXXXXX に作成 # WORKON_HOME set WORKON_HOME=%USERPROFILE%\venv
プロジェクト内に作成したい
# project\.venv\project-XXXXXX に作成 # PIPENV_VENV_IN_PROJECT set PIPENV_VENV_IN_PROJECT=true
Flaskプロジェクト作成
インストール
仮想環境にFlaskをインストールすると、Pipfile.lock
が作成されインストールしたときのバージョンや依存関係のパッケージが記載される。Pipfile.lock
は他のPCで同じ環境を再現する時などに使用。
# Flaskインストール
pipenv install flask
# Pipfile [packages] flask = "*"
アプリ作成
簡単に"HelloWorld"を返すアプリを作成
# project\app.py from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "HelloWorld!"
仮想環境で実行
仮想環境に入り、アプリを実行
# 仮想環境へ入る pipenv shell # Flask起動 (.venv)flask run * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) # ブラウザで'http://localhost:5000'にアクセス # 'HelloWorld' # 仮想環境を抜ける (.venv)exit