oauth2client报KeyError: '_module'错误的原因与修复方法咨询
Hey there, let's break down this error and fix it step by step!
What's Causing This KeyError?
The root issue here is a wrong credential loading approach. You're using a Google Service Account JSON key file, but trying to load it with oauth2client.file.Storage—this class is designed specifically for handling user OAuth2 authorization credentials (like files containing refresh tokens from browser-based logins). Service account JSON has a completely different structure, and it doesn't include the _module field that Storage expects, hence the KeyError.
Is This a Module Bug?
Absolutely not! This is a classic usage mistake. The oauth2client library's Storage and ServiceAccountCredentials are built for distinct scenarios:
Storage: For storing long-term credentials from user-facing OAuth2 flows (e.g., desktop apps requiring user login)ServiceAccountCredentials: For server-to-server authorization (no user interaction needed, perfect for background scripts or scheduled tasks like your weather tracker)
How to Fix This?
We'll refactor the credential loading logic to use the correct service account workflow, and also clean up your JSON parsing (regex is unreliable for this use case).
Modified Full Code
import requests, gspread, time from oauth2client.service_account import ServiceAccountCredentials from datetime import datetime def temperature(): # Define API scopes scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] # Load service account credentials directly (no Storage needed) credentials = ServiceAccountCredentials.from_json_keyfile_name( 'Singapore-Weather-84def2be176a.json', scope ) # Authorize and access the Google Sheet gc = gspread.authorize(credentials) wks = gc.open('Singapore Weather').sheet1 # Fetch weather data and access values directly from JSON (no regex!) r = requests.get('https://api.darksky.net/forecast/b02b5107a2c9c27deaa3bc1876bcee81/1.312914,%20103.780257') current_data = r.json()['currently'] temperature = current_data['temperature'] apparent_temp = current_data['apparentTemperature'] cloud_cover = current_data['cloudCover'] * 100 timenow = datetime.now() # Append data to the sheet wks.append_row([str(timenow), temperature, apparent_temp, cloud_cover]) while True: temperature() time.sleep(3597)
Key Changes Explained
- Removed
Storage&httplib2code: Service accounts don't requireStorage—we load the JSON key directly withfrom_json_keyfile_name. - Replaced regex with direct JSON access: Regex breaks easily if the API's JSON structure changes (e.g., field order, whitespace). Direct key access is far more reliable.
- Simplified authorization flow:
gspread.authorize()acceptsServiceAccountCredentialsdirectly, so we don't need manual HTTP authorization or credential refreshes.
Extra Notes
- Make sure your service account email is added as an editor to the "Singapore Weather" Google Sheet (use the Share button in the Sheet to grant access). Without this, you'll get permission errors.
- Double-check that the
Singapore-Weather-84def2be176a.jsonfile is in the same directory as your script, or use an absolute file path.
内容的提问来源于stack exchange,提问作者jso8910

