AWS Lambdaはプログラム全体ではなく、ハンドラの関数を実行する

Q. Lambdaって、毎回.pyを実行するんじゃないの? A. ハンドラの「関数」を実行する

メッセージそれぞれに対して

print("message: ", message["text"], message["ts"], time.time() - float(message["ts"]))

と時間差を取得してみても、正しい時間差が取れていました。でも毎回同じメッセージを形態素解析してしまっています。

ということは、requests.getが毎回実行されていないかも知れません。ハンドラの関数内部だけが毎回実行されている仮説、つまりハンドラの外で実行していたrequestsである、

res = requests.get(get_url, headers=header, params=payload)

が初回実行時のみ実行されていたら、今起きていることと同じ結果になりそうです。

「lambda ハンドラ」で検索しPython の Lambda 関数ハンドラー - AWS Lambdaを読むと、「関数が呼び出されると、Lambda はハンドラーメソッドを実行します。」と書いてあります。確かにkanehosi_tukeai.pyファイル全体を実行するわけではなく、ハンドラであるpost_77_to_575関数だけを実行していそうです。

すると、可読性は落ちますが単に置き換えると以下のようになります。

import ipadic
import jaconv
import MeCab
import re
import requests
import time


m = MeCab.Tagger(ipadic.MECAB_ARGS) #形態素解析用objectの宣言

def post_message(thread_ts: str, header: dict[str, str], channel_id: str) -> None:
    data  = {
    "channel" : channel_id,# Conversation IDを入れてください
    "text" : "それにつけても金の欲しさよ"
    }
    data["thread_ts"] = thread_ts
    post_url = "https://slack.com/api/chat.postMessage"
    requests.post(post_url, headers=header, data=data)


def extract_hiragana(text: str) -> str:
    return "".join(re.findall(r'[ぁ-ゔー]', text))


def get_pronunciation_list(text: str) -> list[str]:
    m_result = m.parse(text).splitlines() #mecabの解析結果の取得
    m_result = m_result[:-1] #最後の1行は不要な行なので除く
    pro: list[str] = [] #いい感じに切った読み全体を格納する変数
    for v in m_result:
        if '\t' not in v:
            continue
        if v.split('\t')[1].split(",")[0] in ["記号"]:
            continue
        surface = v.split('\t')[0] #表層形
        if len(v.split('\t')[1].split(",")) <= 7:
            continue
        p = v.split('\t')[1].split(",")[7] #読みを取得, 8は発音
        if p == '*':#発音が取得できていないときsurfaceで代用
            p = surface
        if v.split('\t')[1].split(",")[0] in ["助詞", "助動詞"] and pro:
            pro[-1] += p
        else:
            pro.append(p)
    pro = [jaconv.kata2hira(p) for p in pro] #ひらがなをカタカナに変換
    pro = [extract_hiragana(p) for p in pro if p] #余計な記号を削除
    return pro


def is_575(text: str) -> bool:
    words = get_pronunciation_list(text)
    length = 0
    reversed_expected_length_list = [5, 7, 5]
    for word in words:
        if not reversed_expected_length_list:  # 575が終わったのにまだ続く
            return False
        length += len(re.sub(r'[ぁぃぅぇぉゃゅょ]', '', word))  # 1音を構成しない文字
        if length == reversed_expected_length_list[-1]:
            length = 0
            reversed_expected_length_list.pop()
    if reversed_expected_length_list:  # 575と切り取れなかった
        return False
    return True


def post_77_to_575(event, context) -> None:
    token = "xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxx..."# tokenを入れてください
    channel_id = "C0123456789",# Conversation IDを入れてください
    header={
    "Authorization": "Bearer {}".format(token)
    }
    payload  = {
    "channel" : channel_id,
    "limit": 20
    }
    get_url = "https://slack.com/api/conversations.history"
    res = requests.get(get_url, headers=header, params=payload)
    json_channel_history = res.json()
    if "messages" not in json_channel_history:
        print("no message recentry, check token and channel ID")
        return 
    for message in json_channel_history["messages"]:
        print("message: ", message["text"], message["ts"], time.time() - float(message["ts"]))
        if is_575(message["text"]) and time.time() - float(message["ts"]) <= 60:
            post_message(message["ts"], header, channel_id)
    return

if __name__ == "__main__":
    post_77_to_575("", "")

もっと良い変数名などはあると思いますが、とりあえずこれで動きます。

Q. 今度こそ定期判定できてるの? A. スッコココ! それにつけても金の欲しさよ

おめでとうございます。これからずっと「句を詠めば鐘が鳴るなりスッコココ」です。満足するまでリファクタリングしましょう。今回は省きましたが、テスト駆動開発をしていれば、安心してリファクタリングできるはずです。

575にだけ反応してくれるbot(松島の句は、「松島/やあ」と誤判定している)

おわりに

全て読んでくれた人、特にありがとうございます。改めてAWS Lambda で形態素解析〜句を詠めば鐘が鳴るなりスッコココ〜 - estie inside blogを読んでみましょう。高速度合が分かります。そして、AWS Lambda で形態素解析〜句を詠めば鐘が鳴るなりスッコココ〜では分からなくて奥のほそみち編を読んで、読み返して高速道路編が理解できていれば、私はとてもうれしいです。

estieでは社員とSlackメッセージが増えていますがこれで自動的に判定してくれます。忙しい現代人に、つかの間の趣を与えてくれます。575判定的に社員が増えても問題なくなったので、575判定されたい方、1分かかるbotより早く575判定する私にも勝つ自信のある方、入社をお待ちしております。

www.estie.jp

今回はestieが扱うオフィス不動産の話を全くしていないので、不動産の話を聞きたい方もお待ちしております。お疲れ様でした。

© 2019- estie, inc.