树莓派Python gspread OAuth2认证失效:运行一段时间后报401错误
The 401 "UNAUTHENTICATED" error you’re hitting after your script runs for a while comes down to expired OAuth 2.0 access tokens. Service account tokens typically expire after ~1 hour, and your current setup only authenticates once at startup—there’s no logic to refresh the token when it expires. Here are two solid solutions to fix this:
Solution 1: Refresh Credentials in the Loop (Using oauth2client)
If you want to stick with your existing oauth2client setup, modify the loop to check for expired tokens and refresh them before each request:
import gspread from oauth2client.service_account import ServiceAccountCredentials from oauth2client.client import Request 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: # Refresh credentials if the token is expired if credentials.access_token_expired: credentials.refresh(Request()) gc = gspread.authorize(credentials) wks = gc.open('sheet').sheet1 # Re-fetch the worksheet after re-authentication # Your existing code (data collection, processing, etc.) # Add your 2-minute delay here (e.g., time.sleep(120)) wks.append_row(["test", "test2"])
This checks if the token is expired before each append operation and refreshes it if needed, keeping your requests authenticated over time.
Solution 2: Migrate to google-auth (Recommended)
The oauth2client library is deprecated, so switching to the official google-auth library is a more robust long-term fix. It automatically handles token refresh for you in the background:
First, install the required packages:
pip install gspread google-auth google-auth-oauthlib google-auth-httplib2
Then rewrite your script with google-auth:
import gspread from google.oauth2.service_account import Credentials from google.auth.transport.requests import Request scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] credentials = Credentials.from_service_account_file('auth.json', scopes=scope) # Initial refresh if credentials are already expired if not credentials.valid: credentials.refresh(Request()) gc = gspread.authorize(credentials) wks = gc.open('sheet').sheet1 while True: # Your existing code (data collection, processing, etc.) # Add your 2-minute delay here # google-auth will automatically refresh the token if needed before the request wks.append_row(["test", "test2"])
This approach removes the need for manual token expiration checks entirely, as the library manages the token lifecycle behind the scenes.
Quick Checks to Rule Out Other Issues
- Double-check that your service account email (from
auth.json) has edit access to the target Google Sheet (you mentioned it works initially, but permissions might have changed accidentally). - Ensure your
auth.jsonfile hasn’t been modified, corrupted, or moved from its original location.
内容的提问来源于stack exchange,提问作者otto

