AWS Lambda에서 Python을 실행해 보았습니다.

했던 일



AWS를 공부한 후에는 "Qiita 마이페이지에서 LGTM/View/Stock 수의 일람을 확인할 수 있도록 해 보았다"으로 만든 파이썬 파일을 AWS Lambda에서 정기적으로 실행할 수 있도록 해 보았습니다.
(과거 기사에서는 Heroku에서 정기 실행시키고 있었습니다)

정확히 같은 시기에 AWS Lambda에서 파이썬 프로그램 정기 실행 라는 기사가 오르고 있었으므로, 전체의 흐름은 이쪽을 참고로 했습니다.

그런데 추가로 조사한 부분이 있으므로, 이 기사는 그쪽을 메인으로 한 내용이 됩니다.
또한 예를 들어 AWS 계정을 생성했다고 가정합니다.

그건 그렇고, 요금은

AWS Lambda 무료 티어에는 매달 100만 건의 무료 요청과 40만 GB-초의 컴퓨팅 시간이 포함됩니다.

그렇기 때문에 이번과 같이 하루 1회 정도의 리퀘스트라면 문제 없을 것이라면 안심.
(현재 기본 무료로 하고 싶기 때문에, 일단 8$를 넘으면 경고가 날 수 있도록 하고 있습니다)

작성한 Lambda 함수의 내용


  • 런타임: python 3.8
  • 트리거 : 매일 아침 7시에 실행
  • 외부 모듈 (pytz, requests) 사용
  • 타임아웃 시간: 30초
  • 기타: 초기값 그대로



  • 소스 코드



    대개 동일하지만 지난번과 비교하여 다음을 변경했습니다.
  • Qiita 액세스 토큰과 기사 ID를 쓴 쓰기 ⇒ 환경 변수에서로드
  • if __name__ == "__main__":def lambda_handler(event, context):lambda_handler : Lambda 함수로부터 최초로 불리는 함수명

  • 소스 코드

    lambda_function.py
    
    import os
    import http.client
    import json
    import requests
    import datetime
    import pytz
    
    TOKEN = os.environ['TOKEN'] # Read&Write用
    HEADERS = {'content-type': 'application/json',
               'Authorization': 'Bearer ' + TOKEN}
    URL_BASE = 'https://qiita.com/api/v2'
    ARTICLE_ID = os.environ['ARTICLE_ID']
    
    # 記事一覧のLGTM, View, ストック数を取得する
    def get_info():
        url_authenticate = URL_BASE + '/authenticated_user/items'
        # 記事一覧を取得
        res = requests.get(url_authenticate, headers=HEADERS)
        list = res.json()
    
        # 不要な記事を除外
        list_item = []
        for item in list:
            # 限定記事は対象外
            if item['private']:
                continue
            # 投稿先の記事は対象外
            if item['id'] == ARTICLE_ID:
                continue
    
            list_item.append(item)
    
        num = 0
        list_iteminfo = [[0 for i in range(5)] for j in range(len(list_item))]
        for item in list_item:
    
            # 各種項目を取得
            id = item['id']
            title = item['title']
            url = item['url']
            likes_count = item['likes_count']
    
            # 記事の情報を取得
            url_item = URL_BASE + '/items/' + id
            res = requests.get(url_item, headers=HEADERS)
            json = res.json()
    
            # タイトル別のview数のセット
            page_views_count = json['page_views_count']
    
            i = 1
            # stock数の取得(最大1000件)
            while i < 10:
    
                url_stock = url_item + '/stockers?page=' + str(i) + '&per_page=100'
                res_stock = requests.get(url_stock, headers=HEADERS)
                json_stock = res_stock.json()
                stock_num = len(json_stock)
    
                if stock_num != 100:
                    stock_count = (i * 100) - 100 + stock_num
                    break
                else:
                    i += 1
    
            list_iteminfo[num] = [title, url, likes_count, page_views_count, stock_num]
            num += 1
    
        return list_iteminfo
    
    # 記事を更新する
    def update_article(list_iteminfo):
        item = {
                'body': '',
                'coediting': False,
                'private': False,
                'tags': [{'name': 'qiita'}],
                'title': '投稿記事のLGTM, View, ストック数一覧'
                }
    
        # 本文の作成([記事タイトル](URL), LGTM数, View数, ストック数)
        now = datetime.datetime.now(pytz.timezone('Asia/Tokyo'))
        setdate = now.strftime('%Y/%m/%d %H:%M:%S')
        body = 'この記事は [' + setdate + '] に更新されました。\r\n'
        for info in list_iteminfo:
            body += '\r\n[' + str(info[0]) + '](' + str(info[1]) + ')'
            body += '\r\nLGTM:' + str(info[2]) + '件, View:' + str(info[3]) + '件, ストック:' + str(info[4]) + '件\r\n'
    
        item["body"] += body
        url = URL_BASE + '/items/' + ARTICLE_ID
    
        # 記事の更新
        res = requests.patch(url, headers=HEADERS, json=item)
    
        return res
    
    def lambda_handler(event, context):
        list_iteminfo = get_info()
        res = update_article(list_iteminfo)
        print(res)
    



    추가로 조사한 것



    환경 변수 설정



    Qiita의 액세스 토큰등을 환경 변수로 설정하고 싶었습니다만, 코드나 디자이너와 같은 페이지의 「환경 변수」란의 편집 버튼으로부터 간단하게 편집 페이지로 천이할 수 있었습니다.




    외부 모듈 배치 방법



    처음에는 단순히 실행 대상이 되는 lambda_function.py만을 배치했습니다만,"errorMessage": "Unable to import module 'lambda_function': No module named 'requests'"그리고 오류가 발생했습니다. 분명히 외부 모듈이있는 경우 직접 읽을 수 있어야합니다.
    여기을 참고로 로컬 환경에서 lambda_function.py와 같은 계층에 대상 모듈(pytz, requests)을 pip로 설치, zip화하여 업로드했습니다.
    업로드 후 아래와 같이 모듈이 전개되었습니다.



    타임아웃 시간 변경



    외부 모듈도 무사히 읽어내, 이것으로 실행 성공! 라고 생각해, 이번에는Task timed out after 3.00 seconds라는 오류가 발생했습니다.
    초기설정이라면 실행시간이 3초를 넘으면 타임아웃해 버리므로, 이쪽의 설정을 변경합니다.
    환경 변수의 설정과 마찬가지로, 이번은 「기본 설정」란의 편집 버튼으로부터 편집 페이지로 천이해, 설정치를 30초로 변경했습니다.



    마지막으로



    Lambda, 생각보다 쉽습니다.
    다음은 서버 세우거나, 여러가지 시험하고 싶어졌습니다.

    참고



    AWS Lambda에서 파이썬 프로그램 정기 실행
    AWS Lambda 환경 변수 사용
    AWS_Cron 표현식 와일드카드
    AWS Lambda에서 'No module named 'pytz''오류가 발생한 경우 해결 방법
    【AWS】Lambda에서 time out after 3.00 seconds가 나왔을 때의 대처법

    좋은 웹페이지 즐겨찾기