bugfix> python > 投稿

google spreedsheetに2分ごとに行を追加するスクリプトがあります。 スクリプトを開始するとうまくいきますが、しばらくすると次のエラーが表示されます:

{
  "error": {
    "code": 401,
    "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
    "status": "UNAUTHENTICATED"
  }
}

Pythonスクリプト

import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name('auth.json', scope)
gc = gspread.authorize(credentials)
wks = gc.open('sheet').sheet1
while True:
    #here is some other code and 2 minutes delay
    wks.append_row(["test", "test2"])

Auth.json

{
  "type": "x",
  "project_id": "x",
  "private_key_id": "x",
  "private_key": "x",
  "client_email": "x",
  "client_id": "x",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "x"
}

回答 2 件
  • Googleが発行したトークンは、短期間で有効期限が切れる短命のトークンです。ザ・ ServiceAccountCredentials   refresh を持っています  新しいトークンを取得するメソッド。あなたの場合、2分ごとに呼び出されるため、 gc.login() を呼び出すことができます  2分ごと。

    while True:
        gc.login()
    
    

    なぜそれ自体では更新されないのかわかりません(そうすべきです)。参考までに、oauth2clientは非推奨です。他のものの使用を検討してください。 Authlibで使用する方法のヒントを次に示します。https://blog.authlib.org/2018/authlib-for-gspread

  • 認証トークンのタイムアウトは、私の経験では一貫していません-正確に1時間である場合もありますが、それよりもかなり長い(数時間など)場合もあれば、かなり少ない場合もあります。

    サービスアカウント経由で1分ごとにGoogleスプレッドシートにデータを送信するプロジェクトがあります。私が最初に起動したとき、私のスクリプトはKT Workのスクリプトのように配置されていて、メインループの外側で初期ログイン認証が行われていました。言うまでもなく、私は他のみんなと同じように401の不正な失敗に遭遇し始めました。

    そこで、メインループに追加のgc.login()を追加し、45分ごとにトリガーするカウンターを追加しました。まだ401 UNAUTHORIZEDのエラーが発生しているので、30分、20分、わずか10分に減らしましたが、同じエラーが少なくとも1日1回、場合によってはそれ以上発生します。

    私はついにカウンターを取り除き、ループのすべての反復、つまり1分ごとにgc.login()の実行を開始しました。これは一般に401 UNAUTHORIZEDエラーを解決するようですが、万能薬ではありません!どうして?これは、スクリプトを停止するのと同じ効果がある503 UNAVAILABLEエラーが時々発生するためです。

    では、最終的な解決策は何ですか?メインスクリプトを実行する単純なウォッチドッグスクリプトを追加し、失敗した場合は再起動します。いくつかの例を試しましたが、数か月前に見つけたシンプルでエレガントなものに決めました。

    [https://www.alexkras.com/how-to-restart-python-script-after-exception-and-run-it-forever/]

    そこで、次のように独自の「RunScriptForeverWatchdog.py」スクリプトを調整しました。

    #!/usr/bin/python
    from subprocess import Popen
    import sys
    filename = sys.argv[1]
    while True:
        print("\n(Re-)Starting script:  " + filename)
        p = Popen("python " + filename, shell=True)
        p.wait()
    
    

    これで、メインスクリプトを引数としてこのウォッチドッグスクリプトを実行するだけで、後者が失敗するたびに、前者によってすぐに再生成されます。

あなたの答え