📨

Pythonでslackを使う(3): 実用的なslack メッセージ

2022/12/13に公開
2

https://zenn.dev/sergicalsix/articles/f7ad91d1d7cd04

結論

defaultのsend*の引数は使用者自身で設定すると良いです。

import socket
import sys
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

def send_slack_message( channel = 'random', 
                        success = True,
		                send_device_name = True, 
		                send_command = True, 
		                memo = '', 
		                result_file_path = None,
		       ):

    client = WebClient(token=os.environ["SLACK_API_TOKEN"])
    
    if success:
        text = ':tada:\t' #成功を意味する
    else:
        text = ':bomb:\t' #失敗を意味する
    
    if send_device_name:
        text += f'device:{socket.gethostname().split(".")[0]} \t'
    if send_command:
        file_name, args = sys.argv[0], sys.argv[1:]
    text += f'file_name:{file_name} \n' 
	
    # コマンドライン引数が使われている場合
    if args:
        text += f'args:{(" ").join(args)}\n'
    if memo:
        text += f'memo:{memo}\n'
        
    try:
        response = client.chat_postMessage(
            channel=channel,
            text=text,
        )
        if result_file_path:
            response = client.files_upload(
                channels=channel,
                file=result_file_path,
                title=result_file_path
            )
    except SlackApiError as e:
        assert e.response["error"] 


send_slack_message(result_file_path = '_model.py')

実用的なスラックメッセージとは

自分が意識していることは実用的なスラックメッセージ次の3つです。

  1. 一目で内容がわかる
  2. 知りたい情報、必要な情報がある
  3. 不必要な情報がない

上記の3項目を満たすようなスラックメッセージを送ることができる関数(send_slack_message)を考えます。

send_slack_message

1. 一目で内容がわかる

まず"1.一目で内容がわかる"を満たすため、messageの冒頭に絵文字をつけます。
(slackでは:{key}:と書くと、その文字列が登録されている場合に絵文字が表示される。)

こうすることでslackのチャットが流れた時に、プログラムが正常(もしくは異常)に動作しているか一目でわかります。

関数では引数successの値で正常か異常かをプログラムで制御できます。

またsuccess = Falseで使う場合は、例えば以下です。

try:
    #(ある処理)
    send_slack_message()
except:
    send_slack_message(success = False)

2. 知りたい情報、必要な情報がある

次に"2. 知りたい情報、必要な情報がある"については人それぞれあると思います。

私が作成した関数send_slack_messageは以下の情報に対応できています。

  • ステータス(必須)(1で説明済み)
  • デバイス名
  • ファイル名+引数
  • メモ
  • 送りたい結果のファイル

それぞれ下に行くほど情報が多い仕様になっています。

以下必要な項目について説明していきます。

デバイス名

デバイス名はsocket.gethostnameで取得できます。

基本的にローカルでのみ作業する場合は不要ですが、ローカルと(複数の)サーバーでプログラムを動かしている場合は有効です。

環境によっては(例えば貸与PCやサーバーなどで)所属機関などが表示される場合もあるのでsocket.gethostname().split(".")[0]としてPC名のみを取得するようにしています。

ファイル名+引数

引数はsys.argvでリスト形式で取得できます。

またテクニカルな部分ですがsys.argvの1番目以降の要素がなくてもsys.argv[1:]とスライシングを使えばエラーにはなりません。(空のリストが返ってくる)

一方でsys.argvの1番目以降の要素がないときに、sys.argv[1]とするとIndexErrorになります。

一応例のプログラムの入出力を置いておきます。

In [1]: a = [3]
In [2]: a[1:]
Out[2]: []
In [3]: a[1]
--------------------------------------------------------------
IndexError                   Traceback (most recent call last)
<ipython-input-3-8bc71255a22e> in <module>
----> 1 a[1]

IndexError: list index out of range
In [4]:

結果のファイルの送信

ファイルを送信するためにはslack.WebClient.files_upload[1]を用いるとよいです。

そのためにAdd features and functionality->PermissionsからBot Token Scopesにおいてfile:writeの権限を付与する必要があります。

権限を付与できたらInstall your app->Reinstall your Workspaceからアプリを再インストールしてください。

ここで注意点は、slack.WebClient.files_uploadは引数がchannelではなく、channelsであることです。

またslack自体の制限からファイルのサイズを大きくしすぎると(2GB以内だったはず?)送れないので、
結果のpdfpngなどを送るとよいでしょう。

もし実行してうまくいかない場合は、slack_sdkを以下のようにしてupgradeしてみてください。(筆者のversionはslack-sdk==3.19.5)

(venv)% pip install --upgrade slack_sdk

3. 不必要な情報がない

これについては言わずもがなです。

作成した関数では、引数によってスラックメッセージを制御できます。

使用時に引数を変えるか、またはデフォルト引数を変えてカスタマイズするとよいと思います。

またこのようなメッセージは時間の記録が欲しいところですが、slackをメッセージを送る際に時間が表示されるので、あえて入れていません。

最後に

今回は実用的なslackメッセージについて考えました。

作成者の哲学が垣間見える記事となりましたが、参考になれば幸いです。

ご意見(改良案)やご質問あれば是非お願いします!!

次回は最終回を予定しています。

また(面白い?)番外編も予定しています。

( 分量が多い&テクニカルなことも書いたので、SEOの観点からQiitaとかで項目に分けて記事にしようかなとも思っています。)

参考

[1] slack.WebClient.files_upload

https://api.slack.com/methods/files.upload

関連

https://zenn.dev/sergicalsix/articles/f7ad91d1d7cd04

https://zenn.dev/sergicalsix/articles/067065d4eccb9a

Discussion

Kazuhiro SeraKazuhiro Sera

こんにちは!この SDK のメンテナーをしている者です。slack package は古いバージョンとの互換性のために残していて import すると warning が出力されているかと思います。slack_sdk に切り替えてみてください。そのまま動作するはずです!

sergicalsixsergicalsix

ご指摘ありがとうございます!
ご指摘大変助かりました。

slack -> slack_sdkと変更して正しく実行されることが確認できました。(記事でも反映済みです。)