読者です 読者をやめる 読者になる 読者になる

日記とか、工作記録とか

自分に書けることを何でも書いてゆきます。作った物、買ったもの、コンピュータ系の話題が多くなるかもしれません。

Raspberry pi + Twitter : 謎の例外が飛んできても動揺せずにしゃべり続ける

Raspberry pi RaspiParrot Twitter コンピュータ

動作を安定させるために

しばらく動かしたままにしておいた @RaspiParrot ですが、いつの間にか止まっていました。

twitter.com

何か動作不具合が起こっているに違いないのですが、ログではTwitterにアクセスしたところで突然死んでいることしかわかりません。Python-TwitterモジュールはTwitter APIのエラーが発生した場合にTwitterError Exceptionをraiseするようになっており、私のプログラムも例外処理をしているのですが、今回は突然停止していることからそれ以外の例外が発生しているとみられます。このままでは原因追求ができないので、標準エラー出力をファイルに取得しておきました。

pi@pi3:~/twitter$ more boot.sh 
#!/bin/bash

./RaspiParrot.py 1>> log/stdout.log 2>> log/stderr.log &

pi@pi3:~/twitter$

で、今回停止した時に取得された標準エラー出力がこれ。実際にはもっと長いのですが要点を抜粋です。

Traceback (most recent call last):
  File "./RaspiParrot.py", line 201, in CheckMentions
    for state in api.GetMentions():
  File "/usr/local/lib/python3.4/dist-packages/twitter/api.py", line 3430, in GetMentions
    resp = self._RequestUrl(url, 'GET', data=parameters)
  File "/usr/local/lib/python3.4/dist-packages/twitter/api.py", line 4772, in _RequestUrl
    resp = requests.get(url, auth=self.__auth, timeout=self._timeout)
  File "/usr/lib/python3/dist-packages/requests/api.py", line 60, in get
    return request('get', url, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/api.py", line 49, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 457, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 569, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/adapters.py", line 407, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', gaierror(-2, 'Name or service not known'))

つまり接続エラーな訳ですね。今のところ、DHCPIPアドレスの解放と再取得の動作が怪しいと感じていますが、原因追求のためにもう少し細かいエラーを取得することにします。他の問題も起こるかもしれませんし。こんな感じで未知のExceptionも最低限ログが残るようにします。

    try:
        api = twitter.Api(consumer_key=consumer_key,
                       consumer_secret=consumer_secret,
                       access_token_key=access_key,
                       access_token_secret=access_secret,
                       input_encoding=encoding)
        logger.info(u"GetAPI:正常終了")
    except TwitterError as e:
        logger.warning(u"twitter.Api error: %s" % ( e.message ))
    except Exception as e:
        logger.warning(u"Exception[0]%s [1]%s [2]%s" % (sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))

これで再始動して様子見です。少なくとも、エラーが発生してもそのまま死なずにリトライすることを期待しています。さて、何が釣れますやら……