Python Flaskを使ってREST APIを作成する

PythonのフレームワークであるFlaskを使って、GETメソッドとPOSTメソッドに応答するシンプルなREST APIを作成します。

Flaskモジュールインストール

pipでFlaskモジュールをインストールします。

pip install flask flask_restful

Flaskを使ったREST APIのサンプルコード

サンプルコードの仕様

/ GET
クエリパラメータに指定した、nameとageをJSON形式で返却します。

パラメータ
name:必須チェック
age:型チェック(int)

/ POST
クエリパラメータに指定した、q_paramとフォームに指定したf_paramをJSON形式で返却します。

パラメータ
q_param:型チェック(int)※URLから取得
f_param:チェックなし※フォームから取得


実行方法

上記、サンプルコードを”flask_api.py”という名前で保存して以下のコマンドを実行します。

実行コマンド

python flask_api.py

実行結果

$ python flask_api.py 
 * Serving Flask app "flask_api" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 280-531-524
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

ワーニングメッセージ(Flaskビルドインサーバーは開発用サーバーであり、本番環境では利用しない)が表示されていますが、URL”127.0.0.1″のポート”5000″でflaskが起動しています。


GET実行例

Curlコマンドで結果を確認します。

正常系

“name”に”Taro”、”age”に”88″を指定します。
※”127.0.0.1″は、”localhost”に置き換えて下さい

$ curl localhost:5000?name='Taro'\&age=88
{
    "name": "Hello Taro!",
    "age": 88
}

URLに指定したパラメータが返却できています。

異常系

Curlコマンドのオプション”-i”でHTTPヘッダ情報も表示します。

“name”入力なし。必須チェックエラー。

$ curl -i localhost:5000
HTTP/1.0 400 BAD REQUEST
Content-Type: application/json
Content-Length: 67
Server: Werkzeug/1.0.1 Python/3.6.4
Date: Mon, 04 May 2020 15:00:57 GMT

{
    "message": {
        "name": "Name cannot be blank!"
    }
}

“name”指定するが、値を入れない。必須チェックエラー。

$ curl -i localhost:5000?name=
HTTP/1.0 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 43
Server: Werkzeug/1.0.1 Python/3.6.4
Date: Mon, 04 May 2020 15:06:03 GMT

{
    "message": {
        "name": "Name cannot be blank! 2"
    }
}

上記は、abort処理で表示しているエラー。HTTPレスポンスコードは、15行目で指定した”401“が返却されています。

“age”を文字型で入力。タイプエラー。

$ curl -i localhost:5000?name='Taro'\&age=aaa
HTTP/1.0 400 BAD REQUEST
Content-Type: application/json
Content-Length: 68
Server: Werkzeug/1.0.1 Python/3.6.4
Date: Mon, 04 May 2020 15:08:52 GMT

{
    "message": {
        "age": "Age cannot be converted"
    }
}

POST 実行例

正常系

URLパラメータとして”q_param”に”100″を指定し、Curlのオプション”-d”でフォームのパラメータとして、”f_param”に”form_parameter”を指定します。

$ curl -X POST localhost:5000?q_param=100 -d f_param=form_parameter
{
    "post": "Hello World!",
    "qParam": 100,
    "fParam": "form_parameter"
}

URLの文字列、フォームからそれぞれ値が取得できています。

異常系

“q_param”を文字型で入力。タイプエラー。

$ curl -X POST localhost:5000?q_param=query -d f_param=form_parameter
{
    "message": {
        "q_param": "q_param is numbers"
    }
}

公式ドキュメント

上記のサンプルコードは、公式ドキュメントの内容から記載しています。

詳細や最新情報は公式ドキュメントを参照ください

PythonでTwitterAPIを使ってツイートする

Requests、requests-oauthlibを使ってツイートします。twitterというモジュールがある事に後から気づきました。ドキュメントちょっと見た感じでは、使いやすそうな印象を感じました。

参考URL: requests-oauthlib , twitter



事前準備

Pythonモジュールをインストール

Twitter APIへツイート内容をHTTPRequestを送信するためのモジュール、Twitter APIを利用するための認証情報を保存するyamlファイルを扱うモジュールをインストールします。

pip install requests requests_oauthlib pyyaml


Twitter DevelopersからAPIKEYとACCESSTOKENを発行する

Twitter APIを利用するために、Twitter Developersへ登録しAPIKEYとACCESSTOKENを発行します。

Twitter Developers URL


アクセス情報をyamlファイルに保存する

Twitter APIを利用するための、APIKEY、ACCESS TOKENをyamlファイルに保存します。プログラムからこのファイルを読み込んで利用します。

API_KEY: "XXXXXXXXXXXXXXXXXXX"
API_SECRET_KEY: "XXXXXXXXXXXXXXXXXXX"
ACCESS_TOKEN: "XXXXXXXXXXXXXXXXXXX"
ACCESS_TOKEN_SECRET: "XXXXXXXXXXXXXXXXXXX"



サンプルプログラム

※yamlファイルのパスは環境に併せて修正してください


実行コマンド

プログラムを実行してツイートします。

python post_tweet.py

実行結果

https://twitter.com/fukahirer/status/1238738470639525888


正常系

Success.

異常系

Failed.
 - Responce Status Code : 401
 - Error Code : 89
 - Error Message : Invalid or expired token.


おまけ

PythonでTwitterAPIを使ってリプライする

パラメータにリプライするツイートのIDを”in_reply_to_status_id”キーで追加することでリツイートができます。

他のパラメータもあるので、詳細は公式ドキュメントを参照ください。

公式ドキュメントURL

サンプルプログラム

実行結果

https://twitter.com/khidnet/status/1238747528285188096

Python ディレクトリ配下のファイルの一覧を再帰的に取得する

ディレクトリ直下のファイル一覧、ディレクトリ一覧を3つの方法で取得します。

ディレクトリは以下、ファイルはtxtとlogの2種類です。

ディレクトリ、ファイル構成

sample_dir
  │  
  │  f_01.txt
  │  f_02.log
  │
  ├─d_01
  │      f_01_1.txt
  │      f_01_2.txt
  │      f_01_3.txt
  │
  └─d_02
          f_02_1.log


pathlibで ディレクトリ配下のファイル一覧を取得する

pathlib.Pathを利用して、 拡張子を指定したファイル一覧およびディレクトリとファイル一覧を表示する サンプルコード です。

import pathlib

p = pathlib.Path("sample_dir")

# ディレクトリ配下のテキストファイル一覧を表示(拡張子指定)
for f in p.glob("**/*.txt"):
    print(f)

print()

# ディレクトリ配下のディレクトリ、ファイル一覧を表示
for f in p.glob("**/*"):
    print(f)


# - 結果1
# sample_dir\f_01.txt
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt

# - 結果2
# sample_dir\d_01
# sample_dir\d_02
# sample_dir\f_01.txt
# sample_dir\f_02.log
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt
# sample_dir\d_02\f_02_1.log

pathlib.Path関数にディレクトリのパスを指定します。glob関数で取得するサンプルは相対パスですが、絶対パスも指定可能です。

pathlibの詳細については、公式ドキュメントを参照ください。


globでディレクトリ配下のファイル一覧を取得する

globを利用して、拡張子を指定したファイル一覧およびディレクトリとファイル一覧を表示する サンプルコード です。

import glob

TARGET_DIR = "sample_dir"

# ディレクトリ配下のテキストファイル一覧を表示(拡張子指定)
for f in glob.glob(TARGET_DIR + "/**/*.txt", recursive=True):
    print(f)

print()

# ディレクトリ配下のディレクトリ、ファイル一覧を表示
for f in glob.glob(TARGET_DIR + "/**", recursive=True):
    print(f)


# - 結果1
# sample_dir\f_01.txt
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt

# - 結果2
# sample_dir\
# sample_dir\d_01
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt
# sample_dir\d_02
# sample_dir\d_02\f_02_1.log
# sample_dir\f_01.txt
# sample_dir\f_02.log

glob.glob関数にパスを指定します、再帰的に検索する行うには、「recursive」に「True」を指定します。

globの詳細については、公式ドキュメントを参照ください。


walkでディレクトリ配下のファイル一覧を取得する

os.walkを利用して、拡張子を指定したファイル一覧およびディレクトリとファイル一覧を表示する サンプルコード です。


import os

TARGET_DIR = "sample_dir"

# ディレクトリ配下のテキストファイル一覧を表示
for dir_path, dir_names, file_names in os.walk(TARGET_DIR):
    for file_name in file_names:
        if ".txt" in file_name:
            print(os.path.join(dir_path, file_name))

print()

# ディレクトリ配下のディレクトリ、ファイル一覧を表示
for dir_path, dir_names, file_names in os.walk(TARGET_DIR):
    for dir_name in dir_names:
        print(os.path.join(dir_path, dir_name))
    for file_name in file_names:
        f = os.path.join(dir_path, file_name)
        print(f)


# - 結果1
# sample_dir\f_01.txt
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt

# - 結果2
# sample_dir\d_01
# sample_dir\d_02
# sample_dir\f_01.txt
# sample_dir\f_02.log
# sample_dir\d_01\f_01_1.txt
# sample_dir\d_01\f_01_2.txt
# sample_dir\d_01\f_01_3.txt
# sample_dir\d_02\f_02_1.log


os.walk関数にパスを指定します。これまでと違うのは、os.walkでは、ディレクトリパス、ディレクトリ名、ファイル名の3つの戻り値が返却されます。

os.walkの詳細については、公式ドキュメントを参照ください。

Python 型を確認、チェックする

型の確認方法と型チェックをする記載例です。

Python 型を確認する

type(object)

type(1) -> <class ‘int’>


Python 型をチェックする

isinstance(object, class)

isinstance(1, int) -> True

Python 型を確認、チェックする サンプルコード


# int
i = 1
print(type(i))
print(isinstance(i, int))

# str
s = "a"
print(type(s))
print(isinstance(s, str))

# list
l = ["a", 1]
print(type(l))
print(isinstance(l, list))

# dict
d = {"key": "value"}
print(type(d))
print(isinstance(d, dict))

# tuple
t = (1, 2)
print(type(t))
print(isinstance(t, tuple))

print()

# int check.int or listなら True.
print(isinstance(i, (int, list)))
# str check.int or listなら True.
print(isinstance(s, (int, list)))
# list check.int or listなら True.
print(isinstance(l, (int, list)))
# dict check.int or listなら True.
print(isinstance(d, (int, list)))


# ===== 出力例 =====
# <class 'int'>
# True
# <class 'str'>
# True
# <class 'list'>
# True
# <class 'dict'>
# True
# <class 'tuple'>
# True

# True
# False
# True
# False


Python Printを改行なしにする

print関数のデフォルト設定では、出力文字の末尾に改行コードが設定されます。endパラメータを追加することで、変更できます。

Printを改行なしにする

print(“hoge”, end=””)

end=””(空文字)を設定します

Printの区切り文字をなしにする

print(“foo”, “bar”, sep=””)

sep=””(空文字)を設定します

サンプルコード

# デフォルトは末尾が改行コード
print("line_01")
print("line_02")
# 改行なし
print("line_03", end="")
print("line_04")
# カンマ
print("line_05", end=",")
print("line_06")

print()

# 文字列複数
print("foo", "bar")
# 区切り文字をなし
print("foo", "bar", sep="")

# ===== 出力例 =====
# line_01
# line_02
# line_03line_04
# line_05,line_06

# foo bar
# foobar

IBM WatsonのVisual Recognitionの独自クラスで画像認識する (Python)

前回、shellとCurlで利用してみましたが、今回はPythonで独自クラスを利用してみます。

shellとCurlのサンプルコード掲載投稿はこちら

Visual Recognitionで画像認識する

shellとCurlでやったおさらいとなります。アカウントを作成し、APIキーを取得したら、classifyメソッドを利用して画像認識を行います。

画像識別するフルーツの画像

https://watson-developer-cloud.github.io/doc-tutorial-downloads/visual-recognition/fruitbowl.jpg


PythonでWatsonを利用するには、pipで”ibm-watson”モジュールをインストールします。

ibm-watsonモジュールをpipでインストール

# ibm-watsonをインストールする
pip install --upgrade "ibm-watson>=4.1.0"

Python 画像認識 classify サンプルコード

import json
from ibm_watson import VisualRecognitionV3
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

authenticator = IAMAuthenticator("{api keyを設定する}")
visual_recognition = VisualRecognitionV3(
    version="2018-03-19", authenticator=authenticator
)

visual_recognition.set_service_url(
    "https://api.us-south.visual-recognition.watson.cloud.ibm.com"
)

with open("fruitbowl.jpg", "rb") as images_file:
    classes = visual_recognition.classify(
        images_file=images_file,
        accept_language="ja",
        threshold="0.6"
    ).get_result()
    print(json.dumps(classes, ensure_ascii=False, indent=2))

APIKEYとバージョンを指定して、VisualRecognitionインスタンスを生成します。

set_service_urlでエンドポイントのURLを指定します。

VisualRecognitionのclassifyのパラメータに以下を指定します。

  • images_file・・・画像ファイル
  • accept_language・・・言語
  • threshold・・・しきい値(返却される分類のスコアの最低値)


classifyの実行結果

$ python classify.py 
{
  "images": [
    {
      "classifiers": [
        {
          "classifier_id": "default",
          "name": "default",
          "classes": [
            {
              "class": "果実",
              "score": 0.788
            },
            {
              "class": "オリーブ色",
              "score": 0.973
            },
            {
              "class": "レモン・イエロー (色)",
              "score": 0.789
            }
          ]
        }
      ],
      "image": "fruitbowl.jpg"
    }
  ],
  "images_processed": 1,
  "custom_classes": 0
}

結果が取得できました。レスポンスの各値については、公式ドキュメントをご参照ください。

公式ドキュメントURL

https://cloud.ibm.com/apidocs/visual-recognition/visual-recognition-v3?code=python#classify-images


Visual Recognitionで画像認識用の独自クラスを作成する

サンプルで記載されている犬の画像セット3つと猫の画像セット1つを利用して独自クラスを作成します。犬の画像はポジティブ、猫の画像はネガティブな学習データとして利用します。

画像URLは公式ドキュメントのページから取得できます。公式ドキュメントのURLはこちら

Python 独自クラス作成 create_classifier サンプルコード

import json
from ibm_watson import VisualRecognitionV3
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator


def exec():
    authenticator = IAMAuthenticator("{API KEYを設定する}")
    visual_recognition = VisualRecognitionV3(
        version="2018-03-19", authenticator=authenticator
    )

    visual_recognition.set_service_url(
        "https://api.us-south.visual-recognition.watson.cloud.ibm.com"
    )

    with open("beagle.zip", "rb") as beagle, open(
        "golden-retriever.zip", "rb"
    ) as goldenretriever, open("husky.zip", "rb") as husky, open(
        "cats.zip", "rb"
    ) as cats:
        model = visual_recognition.create_classifier(
            "dogs",
            positive_examples={
                "beagle": beagle,
                "goldenretriever": goldenretriever,
                "husky": husky,
            },
            negative_examples=cats,
        ).get_result()
    print(json.dumps(model, indent=2))


if __name__ == "__main__":
    exec()

API KEYを設定してVisualRecognitionインスタンスを生成し、サービスのURLを設定するところまでは、classifyメソッドと同じです。

学習用画像データが入ったzipファイルをwith openで展開します。カンマ区切りで繋げることで、4つのzipファイルを引数に渡します。

独自クラスを作るには、create_classifierメソッド作成します。第一引数には、nameを指定します。positive_examplesでは、犬のクラスを構成する画像ファイルをclassnameキーと一緒に指定します (”beagle”: beagle、”goldenretriever”: goldenretriever、”husky”: husky) 。negative_examplesには、猫の画像ファイルを指定してます。ネガティブ例にはクラス名の指定は不要です。

なお、 .jpgまたは.pngの画像ファイルが 1つのzipに最低でも10個必要で、最大数は10,000画像 または 100MBのようです。

create_classifierの実行結果

$ python create_classifier.py
{
  "classifier_id": "dogs_113492332",
  "name": "dogs",
  "status": "training",
  "owner": "7b33a505-95fc-4f71-a419-17a78f96f78c",
  "created": "2019-12-28T21:19:02.872Z",
  "updated": "2019-12-28T21:19:02.872Z",
  "classes": [
    {
      "class": "husky"
    },
    {
      "class": "goldenretriever"
    },
    {
      "class": "beagle"
    }
  ],
  "core_ml_enabled": true
}

結果が取得できました。レスポンスの各値については、公式ドキュメントをご参照ください。

公式ドキュメントURL

https://cloud.ibm.com/apidocs/visual-recognition/visual-recognition-v3#create-a-classifier

独自クラスを利用するには最初のclassifyメソッドのパラメータに”owners=[“me”]”を追加します。

犬(ハスキー)の画像を独自クラスとデフォルトクラスとで、それぞれ画像認識してみます。

独自クラス classify 実行結果

{
  "images": [
    {
      "classifiers": [
        {
          "classifier_id": "dogs_113492332",
          "name": "dogs",
          "classes": [
            {
              "class": "husky",
              "score": 0.843
            }
          ]
        }
      ],
      "image": "husky2.jpg"
    }
  ],
  "images_processed": 1,
  "custom_classes": 3
}

huskyクラスで、0.843という結果が返却されました。また、独自クラスの言語は日本語指定できないようです。

デフォルトクラス classify 実行結果

{
  "images": [
    {
      "classifiers": [
        {
          "classifier_id": "default",
          "name": "default",
          "classes": [
            {
              "class": "犬",
              "score": 0.98,
              "type_hierarchy": "/動物/哺乳類/肉食動物/イヌ/犬"
            },
            {
              "class": "イヌ",
              "score": 0.887
            },
            {
              "class": "肉食動物",
              "score": 0.887
            },
            {
              "class": "哺乳類",
              "score": 0.887
            },
            {
              "class": "動物",
              "score": 0.982
            },
            {
              "class": "シベリアン・ハスキー",
              "score": 0.739,
              "type_hierarchy": "/動物/飼い慣らされた動物/犬/シベリアン・ハスキー"
            },
            {
              "class": "飼い慣らされた動物",
              "score": 0.883
            },
            {
              "class": "灰白色",
              "score": 0.807
            },
            {
              "class": "緑がかった色",
              "score": 0.79
            }
          ]
        }
      ],
      "image": "husky2.jpg"
    }
  ],
  "images_processed": 1,
  "custom_classes": 0
}

犬で0.98、何故かカタカナのイヌでも0.887、シベリアン・ハスキーが0.739、また色も識別できています。

ハスキーかどうかのスコア0.843>0.739と、独自クラスのほうが優秀だといえるのでしょうか。

しかし、犬が0.98など色々返却されるデフォルトのほうがなんとなく優秀そうな。。。学習量を増やした場合、精度どのくらいあがるかなど、もう少し検証したいと思います。

Python ディレクトリの存在チェックして、存在しなければ作成する

よく使うので、メモ。

Pythonでディレクトリの存在チェックして、存在しなければ作成する

ディレクトリの存在チェックと作成するサンプルコード

import os

SAMPLE_DIR = "sample"

if not os.path.exists(SAMPLE_DIR):
    # ディレクトリが存在しない場合、ディレクトリを作成する
    os.makedirs(SAMPLE_DIR)

os.path.exists関数にディレクトリのパスを渡します。ディレクトリが存在する場合は、True。存在しない場合は、Falseが返却されます。

os.makedirs関数にディレクトリのパスを渡してディレクトリを作成します。

※上記の記述はファイルが存在した場合も、Trueとなります。

長めのサンプルコード

import os

SAMPLE_DIR = "sample2"


# 存在チェック
if os.path.isdir(SAMPLE_DIR):
    print("ディレクトリが存在します")
else:
    print("ディレクトリが存在しません")

# ディレクトリがない場合、作成する
if not os.path.exists(SAMPLE_DIR):
    print("ディレクトリを作成します")
    os.makedirs(SAMPLE_DIR)

# 存在チェック
if os.path.isdir(SAMPLE_DIR):
    print("ディレクトリが存在します")
else:
    print("ディレクトリが存在しません")


長めのサンプルコードでは、ディレクトリの存在チェックにos.path.isdirを利用しています。この関数を利用すれば、ファイルの場合はFalseが帰ってきます。

実行例

>>python check_exists_dir.py

ディレクトリが存在しません
ディレクトリを作成します
ディレクトリが存在します

PythonでUTC⇔JST datetime, POSIX タイムスタンプ(UnixTime)

日付、時刻をよく利用することがあるので、メモとして掲載します。datetimeとPOSIX タイムスタンプ(UnixTime)を相互変換するサンプルコードです。

UTC⇔JSTの変換サンプルコード


解説

各処理の解説です。

利用するモジュールを宣言します。

from datetime import datetime, timedelta, timezone

それぞれ日付を扱うために利用するクラスであり、datetimeは日時を扱い、timedeltaは経過時間(日付や時刻間の差)を扱い、timezoneは、タイムゾーンを扱います。


UTCからJSTを計算する

# 現在時刻(UTC)をdatetime型で取得する
dt_utc = datetime.now(timezone.utc)
print("UTC        : {}, type : {}".format(dt_utc, type(dt_utc)))

# UTC -&amp;gt; JST
JST = timezone(timedelta(hours=+9))
utc_jst = dt_utc.astimezone(JST)
print("UTC -&amp;gt; JST : {}, type : {}".format(utc_jst, type(utc_jst)))

datetime.now()に引数としてtimezone.utcを指定してdatetime型のUTC日時を取得します。 timezone.utc を指定しない場合、ローカル時間(プログラムが実行されているパソコンやサーバーの設定時間)が取得されます。

UTCからJSTへの変換には、datatime.astimezone()にUTCとJSTの時差+9を追加したタイムゾーン(サンプルの場合、JST)を指定します。UTCはデフォルトでtimezone.utcに定義されていますが、JSTは自分で定義する必要があります。


JSTからUTCを計算する

jst_utc = utc_jst.astimezone(timezone.utc)
print("JST -&amp;gt; UTC : {}, type : {}".format(dt_utc, type(dt_utc)))

JSTからUTCを指定する際にも、datetime.astimezone()へUTCのタイムゾーンを指定します。


JSTを取得する

# 現在時刻(JST)をdatetime型で取得する
JST = timezone(timedelta(hours=+9))
dt_jst = datetime.now(JST)
print("JST        : {}, type : {}".format(dt_jst, type(dt_jst)))

datetime.now()へJSTのタイムゾーンを指定します。


datetime -> POSIXタイムスタンプ(UnixTIme)とその逆

# 現在時刻(UTC)をPOSIXタイムスタンプ(float型)で取得する
ts_utc = dt_utc.timestamp()
print("timestamp utc : {}, type : {}".format(ts_utc, type(ts_utc)))

# 現在時刻(JST)をPOSIXタイムスタンプ(float型)で取得する
ts_jst = dt_jst.timestamp()
print("timestamp jst : {}, type : {}".format(ts_jst, type(ts_jst)))

# POSIXタイムスタンプ(float型)をもう一度datetimeに変換する
dt_jst_2 = datetime.fromtimestamp(ts_jst, JST)
print("timestamp -&amp;gt; datatime2 : {}".format(dt_jst_2))
print("datatime == datatime2  : {}".format(dt_jst == dt_jst_2))

datetime.timestamp()でdatetimeをPOSIXタイムスタンプに変換します。

POSIXタイムスタンプをdatetimeに変換するには、timestamp()を使います。

Python pipでよく使うコマンド ( install, upgrade )

よく使うpipコマンドをメモとして掲載します。

pip よく使うコマンド一覧

パッケージ インストールpip install [パッケージ名]
パッケージ インストール(バージョン指定)pip install [パッケージ名]==[バージョンNo]
パッケージ アップグレードpip install -U [パッケージ名]
パッケージ アンインストールpip uninstall [パッケージ名]
パッケージの詳細表示pip show [パッケージ名]
pipインストールパッケージ 一覧pip list
pipインストールパッケージをリストに保存pip freeze > requirements.txt
パッケージリストからpipで一括インストールpip install -r requirements.txt
pip本体のアップグレードpip install -U pip

pip よく使うコマンド一覧

# パッケージ インストール
pip install [パッケージ名]

# パッケージ インストール(バージョン指定)
pip install [パッケージ名]==[バージョンNo]

# パッケージ アップグレード
pip install -U [パッケージ名]

# パッケージ アンインストール
pip uninstall [パッケージ名]

# パッケージの詳細表示
pip show [パッケージ名]

# pipインストールパッケージ 一覧
pip list

# pipインストールパッケージをリストに保存
pip freeze > requirements.txt

# パッケージリストからpipで一括インストール
pip install -r requirements.txt

# pip本体のアップグレード
pip install -U pip


pip よく使うコマンド一覧 解説

各コマンドについて、ざっくり解説します。

パッケージのインストール

パッケージのインストールは、下記のコマンドのみでOKです。何もオプションを指定しないと、最新版(latest)がインストールされます。

#  パッケージのインストール
pip install [パッケージ名]

例) pip install pandas

パッケージのインストール(バージョン指定)

Pythonのバージョンや他のパッケージとの依存関係で特定のバージョンを指定する場合は、下記のコマンドでバージョンを指定します。

# パッケージのインストール(バージョン指定)
pip install [パッケージ名]==[バージョンNo]

例)pip install pandas==0.22.0

パッケージのアップグレード(アップデート)

パッケージを最新バージョンへ更新することをアップグレードといいます。オプションの「-U」または「–upgrade」を指定します。

# パッケージのアップグレード(アップデート)
pip install -U [パッケージ名]
# または
pip install --upgrade [パッケージ名]

例)pip install -U pandas

パッケージのアンインストール

パッケージのアンインストールは半角スペースをいれることで複数同時に実行できます。また、オプションなしだと、削除実施時に、パッケージを本当に削除するかの確認(yの入力を求められる)があります。この削除確認は、「-y」または「–yes」オプションを追加で指定することで省略可能です。

# パッケージのアンインストール
pip uninstall [パッケージ名]
pip uninstall [パッケージ名] [パッケージ名] [パッケージ名]
pip uninstall -y [パッケージ名] [パッケージ名] [パッケージ名]

例)pip uninstall requests pandaas

パッケージの詳細表示

パッケージの詳細情報を表示します。名前、バージョン、作者、ライセンス、依存パッケージなどが表示されます。

# パッケージの詳細表示
pip show [パッケージ名]

例)pip show pandas

pipインストールパッケージ 一覧

pipを利用してインストールしたパッケージの名前、バージョンを表示します。オプション「-o」(「–outdated」でもOK)をつけると、最新でないパッケージのバージョンと最新バージョンの一覧を表示します。

# pipインストールパッケージ一覧
pip list

# 最新でないパッケージのバージョンと最新バージョン一覧
pip list -o
または
pip list --outdated

pipインストールパッケージをリストに保存

pipを利用しているパッケージ一覧を保存します。このファイル(今回はテキストファイル)を利用して、環境のバックアップをとったり、他のマシンへ同じ環境を構築します。

「pip freeze」でパッケージとバージョンを表示し、「>」で書き込みを指定し、「requirements.txt」というファイル名で保存します。

# pipインストールパッケージをリストに保存
pip freeze > requirements.txt

パッケージリストからpipで一括インストール

オプションの「-r」をつけることで、ファイルからパッケージを一括でインストールします。

# パッケージリストからpipで一括インストール
pip install -r requirements.txt

pip 自体のアップグレード

pip自体のアップグレードです。ワーニングがでたら、最新版に更新しています。

# pip本体のアップグレード
pip install -U pip

# または
python -m pip install --upgrade pip

PythonでLINE、Slack、Discordへメッセージ、通知を送る

Pythonでアプリにメッセージや通知を送るためのサンプルコードです。

PythonでLINE、Slack、Discordへメッセージ、通知を送る

LINE、Slack、Discordといったアプリにメッセージや通知を送るには、Pythonプログラムから各アプリのメッセージ受信アドレス(URL)へHTTPリクエスト(https)を送信します。

今回は下記のモジュールを利用して、HTTPリクエストを送信します。

# requestsをインストール
pip install requests

今回は、requestsモジュールを利用しますが、標準モジュールのurllibを利用するなど、他の方法でもメッセージを送ることが可能です。

PythonでLINE、Slack、Discordへメッセージ、通知を送る

では、先にサンプルコードを掲載します。

サンプルコード


解説

では、それぞれ解説です。

LINEにPythonでメッセージ、通知を送る

LINEへメッセージを送るためには、LINE notifyというサービスを利用する必要があります。

LINE notifyの公式URLはこちら

このサービスを登録すると、LINE notifyのURLにメッセージ(HTTPリクエスト)を送信すると、送ったメッセージをLINE通知として転送してくれます。LINEの通知先は、LINE notifyの公式URLからログインし、設定画面から登録します。※グループのみ登録可能だったはずです

LINEにPythonでメッセージ、通知を送るサンプルコード

def line_notify(token, message):
    """
    LINE send message.

    Args:
        token (str): line notify token.
        message (str): message.
    """
    LINE_NOTIFY_URL = 'https://notify-api.line.me/api/notify'
    if token:
        requests.post(LINE_NOTIFY_URL,
                      headers={'Authorization': 'Bearer {}'.format(token)},
                      data={'message': '\n{}'.format(message)})

line_notifyメソッドでLINEにメッセージを送信します。引数1には、LINE notfyで取得したトークン、引数2には、送信するメッセージを設定します。

「LINE_NOTIFY_URL 」には、LINE notifyのURLを固定で指定しています。
「if token」でトークンが設定されているかを判定しています。
「requests.post」メソッドで、LINE notifyのURLにHTTPリクエスト(POST)を送信します。headersには、LINE notfyで取得したTokenを設定し、dataにはメッセージを設定しています。


SlackにPythonでメッセージ、通知を送る

Slackにメッセージを送るには、slack incoming-webhookを利用します。

Webhookとは、外部システムからSlack送られてくるHTTPリクエストのことで、今回の場合、PythonプログラムからSlackへ送るメッセージのことを指します。

Slackのincoming-webhookを利用するにはこちらのページにアクセスし、「Create a Slack app」をクリックします。

前述のLINEでもそうでしたが、Slack、Discordにメッセージを送るということは、いずれの場合も、こちらのプログラム(PythonじゃなくてもOK)から各サービスの受信用URLにHTTPリクエストを送信し、リクエストを受信したサービス側で自動的にそれぞれのアプリの形式でメッセージ通知してくれるという処理の流れになります。

SlackにPythonでメッセージ、通知を送るサンプルコード

def slack_notify(url, message):
    """
    Slack send message.

    Args:
        url (str): slack incoming-webhook url.
        message (str): message.
    """
    if url:
        requests.post(url,
                      data=json.dumps({'text': message}))

slack_notifyメソッドでSlackにメッセージを送信します。引数1には、slack incoming-webhookで取得したURL、引数2には、送信するメッセージを設定します。

「if url」でurlが設定されているかを判定しています。
「requests.post」メソッドで、slack incoming-webhookのURLにHTTPリクエスト(POST)を送信します。urlにslack incoming-webhookを設定し、dataにはJSON形式でメッセージを設定しています。


DiscordにPythonでメッセージ、通知を送る

Discordにメッセージを送るには、Discord webhookを利用します。

Discordのwebhookを利用するには、チャンネルの編集からWebhookの設定を行います。

DiscordにPythonでメッセージ、通知を送るサンプルコード

def discord_notify(url, message):
    """
    Discord send message.

    Args:
        url (str): discord webhook url.
        message (str): message.
    """
    if url:
        requests.post(url,
                      data={'content': message})

discord_notifyメソッドでDiscordにメッセージを送信します。引数1には、discord webhookで取得したURL、引数2には、送信するメッセージを設定します。

「if url」でurlが設定されているかを判定しています。
「requests.post」メソッドで、discord webhookのURLにHTTPリクエスト(POST)を送信します。urlにdiscord webhookを設定し、dataにはJSON形式でメッセージを設定しています。