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"
}
認証トークンのタイムアウトは、私の経験では一貫していません-正確に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()
これで、メインスクリプトを引数としてこのウォッチドッグスクリプトを実行するだけで、後者が失敗するたびに、前者によってすぐに再生成されます。
関連記事
- インポート後のPythonノートブックのキーエラーの解決
- PythonでJSONファイルにデータを保存するときにエラーが発生しました
- Pythonで壊れたパイプエラーを修正する方法は? (IRCクライアントでの作業)
- クラスの属性エラー:Python:pycharmで
- Pythonのエラー:名前が定義されていません(ifステートメントの変数)
- djangoチャネルを使用してPython36からPython37にアップグレードする際のSynchronousOnlyOperationエラー
- Python:単純なforループ構文エラー
- beautifulsoupでスクレイピングしようとしたときにPythonループでエラーが発生しました
- Python @ attrsは、オプションの属性を持つオブジェクトを作成するときにエラーを引き起こします
- リスト内包表記のエラーを除いてPythonが使用されないのはなぜですか
Googleが発行したトークンは、短期間で有効期限が切れる短命のトークンです。ザ・
ServiceAccountCredentials
refresh
を持っています 新しいトークンを取得するメソッド。あなたの場合、2分ごとに呼び出されるため、gc.login()
を呼び出すことができます 2分ごと。なぜそれ自体では更新されないのかわかりません(そうすべきです)。参考までに、oauth2clientは非推奨です。他のものの使用を検討してください。 Authlibで使用する方法のヒントを次に示します。https://blog.authlib.org/2018/authlib-for-gspread