サーバーからちょっとしたメール送信をしたいときに何かしらのSMTPサーバー経由でメールを送りたいなと思ったので
ひとまず、簡単なメール通知をGoogleのSMTPサーバーを使って送る例をメモっておく

GoogleのSMTPを使ってメール送信する際には、アプリのパスワードを作成する必要がある
手順は、以下ページのとおり
Googleでアプリパスワードを生成

C#での実装
using System;
using System.Net;
using System.Net.Mail;

const string appPassword = "your-app-password"; // アプリのパスワード

var mailAddressFrom = "youraddress@gmail.com";  // 送信者
var mailAddressTo = "送信先メールアドレス";     // 受信者
var subject = "テストメール";                   // タイトル
var body = "プログラムから送信しています";      // 本文

// SMTP設定
var smtp = new SmtpClient("smtp.gmail.com", 587)
{
    EnableSsl = true,
    Credentials = new NetworkCredential(mailAddressFrom, appPassword)
};

var mail = new MailMessage(mailAddressFrom, mailAddressTo, subject, body);

try
{
    smtp.Send(mail);
    Console.WriteLine("メールを送信しました。");
}
catch (Exception ex)
{
    Console.WriteLine("送信エラー: " + ex.Message);
}
var mailAddressFrom = "youraddress@gmail.com"; // 送信者
var mailAddressTo = "送信先メールアドレス";    // 受信者
var subject = "テストメール";                  // タイトル
var body = "プログラムから送信しています";     // 本文

// SMTP設定
var smtp = new SmtpClient("smtp.gmail.com", 587)
{
    EnableSsl = true,
    Credentials = new NetworkCredential(mailAddressFrom, appPassword)
};

var mail = new MailMessage(mailAddressFrom, mailAddressTo, subject, body);

try
{
    smtp.Send(mail);
    Console.WriteLine("メールを送信しました。");
}
catch (Exception ex)
{
    Console.WriteLine("送信エラー: " + ex.Message);
}
Python
import smtplib
from email.mime.text import MIMEText

APP_PASSWORD = "your-app-password" # アプリのパスワード

mailAddressFrom = "youraddress@gmail.com" # 送信者
mailAddressTo   = "送信先メールアドレス" # 受信者
subject = "テストメール"
body = "プログラムから送信しています"

msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = mailAddressFrom
msg['To'] = mailAddressTo

try:
    smtp = smtplib.SMTP("smtp.gmail.com", 587)

    # SMTPでTLS通信をするためのお作法
    smtp.ehlo() 
    smtp.starttls()
    smtp.ehlo()

    smtp.login(mailAddressFrom, APP_PASSWORD)
    smtp.sendmail(mailAddressFrom, mailAddressTo, msg.as_string())
    smtp.close()
    print("メールを送信しました。")

except Exception as e:
    print(f"送信エラー: {e}")

投稿日時: 2025-06-07 16:02:07
更新日時: 2025-06-08 02:36:08

C#でアプリ作っているけども、C#だと機能的にたりずPythonなら・・・という場面に出くわしたので簡単なAPIのサービス立てて内部から呼び出して使えたら幅がひろがりそうなので読んでみる

「Python FlaskによるWebアプリ開発入門 物体検知アプリ&機械学習APIの作り方」

投稿日時: 2025-06-05 10:21:05

ルーティング

関数の前に @app.route(ルート) を設定する

@app.route("/")
def index():
    return "Test"

@app.route("/hoge")
def index():
    return "foobar"

methodsを省略するとGETとなります

methodの指定

GET以外を指定するのであればmethodsに配列で指定

@app.route("/", methods=["GET", "POST"])
def sample():
    return "hogehoge"

Flask 2.0以降では、以下のようにもかける

@app.get("/")
@app.post("/")
def sample():
    return "hogehoge"

これは、厳密には、以下のようにapp.routeを2回実行しているのと同等らしい

@app.route("/", methods=["GET"])
@app.route("/", methods=["POST"])
def sample():
    return "hogehoge"

尚、methodで処理を振り分けるには、from flask import requestを追加し、
request.method で判定する

任意のルートを受けるようにする

ルーティングに変数を設定し、任意のルートをうける

@app.route("/animal/<name>")
def sample(name):
    if(name == "cat"):
        return "ニャー"
    elif(name == "dog"):
        return "ワン"
    else:
        return "???"

/animal/cat ならニャーを返すといった感じになる
<>を設定したら、関数の引数に受ける必要あり

さすがになんでもうけるってのも問題だと思うので・・・

コンバーター

所定のパスをうけるよにするために指定する
blogとかで記事のidを受けたい場合は

from flask import Flask

app = Flask(__name__)

@app.route("/blog/<int:id>")
def sample(id):
    return str(id)

カスタムコンバーター

デフォルトのコンバーターだと足りないので、コンバーターをカスタムで作る
例えば正規表現に該当するパスだけ受け付ける場合

from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)

class RegexConverter(BaseConverter):
    def __init__(self, url_map, *items):
        super().__init__(url_map)
        self.regex = items[0]

app.url_map.converters['regex'] = RegexConverter #カスタムコンバーター追加

@app.route("/aaa/<regex('\d{4}-\d{2}-\d{2}'):date>")
def sample(date):
    return date

ルートの確認

flask routesを実行するとルートの一覧を確認できる

投稿日時: 2025-05-31 15:16:31
更新日時: 2025-06-01 10:36:01

さらっとだけ触ってみたのでメモ

とりあえず起動してみる

pyenv、poetryを使って、Hello Flask!

# プロジェクトを作成し、その中に移動
mkdir sample
cd sample

# ローカルで使用するPythonのバージョンを指定
pyenv local 3.9.7

# 対話無しデフォのpyproject.toml作成  
poetry init --no-interaction

# flaskを追加
poetry add flask

引数無しの poetry init を実行すると

This command will guide you through creating your pyproject.toml config.
Package name [sample]:
Version[0.1.0]:
Description []:
Author [None, n to skip]:
License []:
Compatible Python versions [>=3.9]: 
Would you like to define your main dependencies interactively? (yes/no) [yes] 
Would you like to define your development dependencies interactively? (yes/no) [yes] 

AuthorはNone、Would you~は、Noで他はEnterで
pyproject.tomlの中身

[project]
name = "sample"
version = "0.1.0"
description = ""
authors = [
    {name = "Your Name",email = "you@example.com"}
]
readme = "README.md"
requires-python = ">=3.9"
dependencies = [
]


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

ちょっと学習のためコードかくためくらいであれば、都度tomlを作りこむ必要もないので、対話せずにデフォルトのファイルを作ってもらうのが以下
poetry init --no-interaction

とりあえずapp.pyを作成

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello Flask!!"

if __name__ == "__main__":
    app.run()
# poetry 2.0以降はshellがデフォルトでは使えないとのことで追加
poetry self add poetry-plugin-shell

# shellに入る
poetry shell

# 実行
python app.py

実行すると http://127.0.0.1:5000 として実行される
止めたければ Ctrl + C

shell からぬけるには、 exit か Ctrl+D

shellを使わないのであれば
poetry run python app.pyで実行(都度poetry run をつける)

あらためてapp.pyを読んでみる

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello Flask!!"

if __name__ == "__main__":
    app.run()
from flask import Flask

flaskパッケージのFlaskクラスを使用する

参考…importしたものが何なのか調べたければ print(type(Flask)) みたいに書いて出力させれば・・・
<class 'type'> このような出力が得られるます

app = Flask(__name__)

テンプレート、静的ファイルなどのリソースを探す場所をFlaskに教えるもの

@app.route("/")

関数の前につけることで、このルートを指定されたら実行してくださいという指示をしています
デコレータと呼ぶらしい。

C# Asp.netだと関数の前にRouteのアノテーションを指定した場合と一緒ですね

[Route("/")]
public IActionResult hello(){
}
if __name__ == "__main__":
    app.run()

開発サーバーでflaskアプリを起動
本番であれば、本稼働用のWSGIサーバーを使用することになるが、これをかいておくのも一つの手 debugモード(エラーがあった場合画面で表示)で実行するなら

if __name__ == "__main__":
    app.run(debug=True)

起動方法

shellに移動し、python app.py で実行したが shellに移動せずに、poetry run python app.pyでもよいし
poetry fun flask run のようにflask runで実行でもよい 補足・・・flask runの場合以下は不要

if __name__ == '__main__':
    app.run()

flask runの場合、ターミナルのカレントにあるソースに起点が存在していないと見つけられないといわれてしまう つまり、静的ファイルやら他のものもあり、ソースをフォルダ階層で分けた場合の話
apps/app.py のように分けましたとなるとルート階層でflask run と書いても実行されない。

poetry run python apps\app.py のように明示的にパスを含めて実行するか
フォルダを移動し、appsに入ってから poetry run flask run とするか

環境変数 FLASK_APP にアプリの場所を設定し それをもとに実行してもらう

$env:FLASK_APP = ".\apps\app.py"

powershellならこんな感じ。セッション中のみ有効な環境変数設定なのでターミナル抜ければ消えます

これがあれば poetry run flask run でも実行できます

ちなみに、 FLASK_ENVにdevelopmentを指定しておけば、デバッグモードとして実行になる

$env:FLASK_ENV = "development"

ホットリロード

DEVELOPMENTだとホットリロードが有効だと思っていたのだけど
flask runの起動時のログをみると

 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000

Debug modeのon offと Develomentはまた別物とのこと。
FLASK_ENVにdevelopmentを指定するとその両方が切り替わるはずだが・・・

生成AIの見解。

Flask 2.3 からは FLASK_ENV の使用は非推奨 になっています。

代わりに:

flask --app apps.app --debug run

とのこと

最終的に…

いろんなことを考慮していくと、楽に起動できるということと起動方法の選択しを広げた感じにするなら・・・

こんな手順でしょうか

# プロジェクト作成
mkdir sample
cd sample

#ここでは3.9.7をつかうとする 

pyenv local 3.9.7
poetry init --no-interaction

poetry add flask

# フォルダ分けしたくなった場合を考慮していったんフォルダに入れた場合でも実行できることを考えてみる
mkdir apps

.\apps\app.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "Hello, Flask!"


if __name__ == '__main__':
    # これは開発サーバー専用。デプロイ時は使われないので記載してあっても問題なし
    app.run(debug=True)
# shellが楽なので使いたい
poetry self add poetry-plugin-shell
poetry shell
flask --app apps.app --debug run

flask run じゃなくとも python .\apps\app.pyでも動く

リンク

公式サイト https://flask.palletsprojects.com/en/stable/

有志による日本語訳サイト
https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/

ソースが気になる場合

flaskがきになる・・となった場合
公式のGitHubを見に行くか https://github.com/pallets/flask

flaskのクラスであれば
https://github.com/pallets/flask/blob/main/src/flask/app.py

poetryでローカルにインストールしたソースをみるのであれば・・・
poetry env info --path でローカルのパスを調べて
Libフォルダ内にあるflaskの中を見に行く

投稿日時: 2025-05-30 13:59:30
更新日時: 2025-06-01 08:17:01

windows11でPythonを使っていくための準備をします(WSLは使わないです)
pyenv-winでPythonのバージョン管理と、Poetryを使ってPythonパッケージのインストールをします

Chocolatey

まずは、 MacやLinuxでは、Homebrewというパッケージ管理システムがありますが
Windowsでは、Chocolateyというパッケージ管理システムがあります。

便利なので入れておくとよいと思います
インストール方法は、過去記事参照

pyenv-winのインストール

pyenvは、複数のPythonのバージョンを管理し、プロジェクトごとに切り替えて使うための仕組みです

windowsだと pyenv-win がそれに該当します

Chocolateyでインストールするので、PowerShell(管理者)を実行し、インストール

choco install pyenv-win

インストールできたかは、PowerShell(管理者)を起動しなおしてバージョンの確認を行う

pyenv --version
pyenv 3.1.1

pyenvの使い方

# pyenvのバージョン
pyenv --version

# インストール
pyenv install <バージョン>

# インストール可能なバージョン一覧
pyenv install --list

# インストール済み使用可能なpythonのバージョン
pyenv versions

# Pythonのバージョン切替
pyenv global <バージョン>

pyenv local <バージョン>

pyenv local は、実行するとカレントディレクトリに .python-versionファイルが作成され、その中フォルダで実行すると指定したバージョンのPythonで実行できる。

poetryのインストール

引き続き、PowerShellで下記コマンドを実行

(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

参考: https://python-poetry.org/docs/#installing-with-the-official-installer

実行すると以下メッセージが表示されます

Retrieving Poetry metadata

# Welcome to Poetry!

This will download and install the latest version of Poetry,
a dependency and package manager for Python.

It will add the `poetry` command to Poetry's bin directory, located at:

C:\Users\{ユーザー名}\AppData\Roaming\Python\Scripts

You can uninstall at any time by executing this script with the --uninstall option,
and these changes will be reverted.

Installing Poetry (2.1.2)
Installing Poetry (2.1.2): Creating environment
Installing Poetry (2.1.2): Installing Poetry
Installing Poetry (2.1.2): Creating script
Installing Poetry (2.1.2): Done

Poetry (2.1.2) is installed now. Great!

To get started you need Poetry's bin directory (C:\Users\{ユーザー名}\AppData\Roaming\Python\Scripts) in your `PATH`
environment variable.

You can choose and execute one of the following commands in PowerShell:

A. Append the bin directory to your user environment variable `PATH`:

```
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";C:\Users\{ユーザー名}\AppData\Roaming\Python\Scripts", "User")
```

B. Try to append the bin directory to PATH every when you run PowerShell (>=6 recommended):

```
echo 'if (-not (Get-Command poetry -ErrorAction Ignore)) { $env:Path += ";C:\Users\{ユーザー名}\AppData\Roaming\Python\Scripts" }' | Out-File -Append $PROFILE
```

Alternatively, you can call Poetry explicitly with `C:\Users\{ユーザー名}\AppData\Roaming\Python\Scripts\poetry`.

You can test that everything is set up by executing:

`poetry --version`

このパスにインストールされていて
C:\Users{ユーザー名}\AppData\Roaming\Python\Scripts

削除したい場合は、 --uninstal オプションで実行すればよいとのこと

環境変数にこのパスを追加してね とも書いてありますね。
ご丁寧にパス追加のコマンドまで書かれているのでそれを実行します

PowerShellを再起動して poetry --versionを実行すると
Poetry (version 2.1.2)
のようにバージョンが表示されればOKです

使い方の流れ

プロジェクトを作成
poetry new [project-name]

追加するパッケージがあれば追加します
poetry add [package-name]

特定のバージョンを追加したい場合
poetry add [package-name]@[version]

開発で使用するパッケージを追加したい場合
poetry add --dev [package-name]

パッケージのインストール(仮想環境の作成)
poetry install

パッケージのアップデート
poetry update

事前に何が変更されるか確認したい場合は、
poetry update --dry-run

不要なパッケージの削除
poetry remove [package-name]

特定のPythonバージョンで実行したい場合
pyenv local [バージョン]

仮想環境で実行
poetry run python

仮想環境に移動して実行
poetry shell
python [python-file-name]

参考: 生成AIさん、開発で追加すると便利なパッケージってなーにー?

  1. テスト関連
    pytest: テストフレームワーク。シンプルな構文でユニットテストを記述可能。 pytest-cov: テストカバレッジ計測ツール。コードのテスト範囲を可視化。 requests-mock: HTTPリクエストのモック作成。APIテスト時に外部依存を排除。

  2. コード品質管理 flake8: コードスタイルチェック(PEP8準拠)。 black: 自動コードフォーマッター。一貫したスタイルを強制。 mypy: 静的型チェッカー。型アノテーションの誤りを検出。

  3. ドキュメンテーション Sphinx: プロフェッショナルなドキュメント生成。Python公式ドキュメントも採用。 mkdocs: Markdownベースの軽量ドキュメントツール。

  4. 開発支援ツール ipython: 対話型シェル。デバッグやプロトタイピングに便利。 jupyter: ノートブック環境。データ分析や可視化の実験用。

  5. 環境構築・デプロイ twine: PyPIへのパッケージアップロード用。 docker-compose: コンテナ環境の管理(Docker連携)。

  6. その他 pre-commit: Gitコミット前の自動チェック(テスト、リントなど)を実行。 bandit: セキュリティ脆弱性スキャン。

投稿日時: 2025-04-12 06:01:12
更新日時: 2025-05-30 13:11:30

forループでループを抜けきったらelseに入ることを利用して
elseでcontinueしておけば、内側のループがすべて実行されたことになり
breakで抜けた場合はelseを通過しないのでその先のbreakでぬけることで
ループをぬけれる。
下記は、各要素の合計が30を超えるのであれば抜ける処理

dataList = [
        [2, 4, 5, 6],
        [6, 4, 1, 5],
        [3, 1, 3, 1]
    ]

sum = 0
for rowData in dataList:
    for value in rowData:
        print("Next", value)
        if 30 < sum + value: 
            break
        sum += value
        print(sum)
    else:
        continue
    break;
投稿日時: 2024-07-13 12:53:13

Pythonは普段触らないのでメモ。

四則演算
print(f"10 +  3 = {10 +  3}") # 13
print(f"10 -  3 = {10 -  3}") # 7
print(f"10 *  3 = {10 *  3}") # 30
print(f"10 /  3 = {10 /  3}") # 3.33333333
print(f"10 // 3 = {10 // 3}") # 3
print(f"10 %  3 = {10 %  3}") # 1
print(f"10 ** 3 = {10 ** 3}") # 1000
文字列のメソッド ・大文字、小文字変換
print("Python".upper()) # PYTHON
print("Python".lower()) # puthon
・含む文字の数
s = "G" + ("o" *10) + "gle"

print(s.count("o")) # 10 print(s.count("oo")) # 5 print(s.count("ooo")) # 3

print(s.count('o', 5)) # 6 Goooo ooooole print(s.count('o', 5, 8)) # 3 Goooo ooo oole

・文字列の位置を取得

s = "abcdefgabcdefg"

print(s.find("a"))      # 0
print(s.find("a", 3))   # 7
print(s.find("a", 10))  # -1 該当なし

# 後ろから探す
print(s.rfind("a"))     # 7

・トリム

s = "   \tabc\t"
print(f"|{s}|")
print(f"|{s.lstrip()}|") #左側をトリムする
print(f"|{s.strip()}|")  #左右トリムする
print(f"|{s.rstrip()}|") #右側をトリムする

・フォーマット

from datetime import datetime, timedelta

date_start = datetime.now()
date_end = date_start + timedelta(days=7)

# 文字列に直接埋め込むと…メソッド形式だと長すぎて可読性が悪い
print(f"開始:{date_start.strftime('%Y-%m-%d')} - 終了:{date_end.strftime('%Y-%m-%d')}")

# だからといって直接埋め込むために変数に設定しなおすべきか・・・
date_start_str = date_start.strftime("%Y-%m-%d")
date_end_str =date_end.strftime("%Y-%m-%d")
print(f"開始:{date_start_str} - 終了:{date_end_str}")

# 埋め込みたいものが長い場合はformatのほうが読みやすいかも
print("開始:{} - 終了:{}".format(date_start.strftime('%Y-%m-%d'), date_end.strftime('%Y-%m-%d')))
複数データ
data_list = [1, 2, 3] 
print(data_list)  # [1, 2, 3]

data_tuple = (1, 2, 3) print(data_tuple) # (1, 2, 3)

data_set = {1, 2, 3, 1, 2, 3} print(data_set) # {1, 2, 3}

data_disc = {"a" : 1, "b" : 2, "c" : 3} print(data_disc) # {'a': 1, 'b': 2, 'c': 3}

文字列に変数埋め込み

f"…{変数名}…"

from datetime import datetime

now = datetime.now().strftime("%H:%M:%S")
print(f"現在の時間:{now}")

num = 10
print(f"数値は{num}")
条件分岐/繰り返し ・if文 (インデントで
val = input("1:xxx, 2:xxx, 3:xxx\n選択してください。")

if val == "1": print("1:xxx を選択しました") elif val == "2": print("2:xxx を選択しました") elif val == "3": print("3:xxx を選択しました") else: print("選択外です")

if文の中 or 外はインデントで決まる。

・and, or &&, || ではなく and, or
ちなみに、2 <= val and val <= 10 は 2 <= and <= 10 ともかけるとのこと。

・notでtrueとみなすもの(falsyな値) False / None / 0 / 空(文字列、シーケンス、コレクションなど)

・while文

while True:
    val = input("1-3の数値を入力してください")
    
    if not val.isdigit():
        print("整数値じゃありません")
        continue
    elif val == "1":
        print("1を選択しました")
    elif val == "2":
        print("2を選択しました")
    elif val == "3":
        print("3を選択しました")
    else:
        print("1-3以外が選択されました。終了します。")
        break

print("終了します")

while 条件:
else:
whileのelseは条件が偽となったときにだけ実行される。
breakで終了となったときは、実行されない

・for文

sum = 0
for i in range(1, 11): #1から10までの値 
    sum += i
    print(sum)

data = [1, 3, 5, 7, 11, 13] #
for n in data:
    print(n)
例外
import sys

try:
    value = 1/0

except:
    ex_type, ex_value, ex_traceback = sys.exc_info()

    print(f"Type:{ex_type}")   #Type:<class 'ZeroDivisionError'>
    print(f"Value:{ex_value}") #Value:division by zero

finally:
    print("後処理")
投稿日時: 2024-07-12 13:28:12
更新日時: 2024-07-13 13:12:13

最近の投稿

最近のコメント

タグ

アーカイブ

その他