使用Google Sheets API后,跨Python文件调用变量遇AttributeError问题
解决Python模块间变量调用的AttributeError问题
问题背景
尝试通过Google Sheets API拉取表格数据,转换为逗号分隔字符串后传递给短信发送脚本,但调用存储字符串的变量时出现错误:AttributeError: module 'sheetsReader' has no attribute 'result_string'。首次使用Python多模块开发,不确定是否需要像Java那样定义类,或遗漏了关键步骤。
原代码展示
sheetsReader.py
import os from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] value = [] global result_string def main(): credentials = None if os.path.exists("tocken.json"): credentials = Credentials.from_authorized_user_file("token.json", SCOPES) if not credentials or not credentials.valid: if credentials and credentials.expired and credentials.refresh_token: credentials.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES) credentials = flow.run_local_server(port=0) with open("token.json","w") as token: token.write(credentials.to_json()) try: service = build("sheets", "v4", credentials=credentials) sheets = service.spreadsheets() result = sheets.values().get(spreadsheetId=SPREADSHEET_ID, range="Sheet1!A1:A9").execute() values = result.get("values", []) for row in values: value.append(row) result_string = ', '.join([inner_list[0] for inner_list in value]) except HttpError as error: print(error) if __name__ == "__main__": main()
短信发送脚本(示例命名为sms_sender.py)
from datetime import time, timedelta, datetime import Alert import time as tm import sheetsReader text = sheetsReader.result_string def job(): Alert.email_alert("todo","stop", "4807931338@vtext.com") schedule.every().day("7:20").do(job) while True: schedule.run_pending() tm.sleep(1)
错误原因分析
- 全局变量声明错误:函数外部的
global result_string写法无效,Python中需在函数内部声明global result_string才能修改全局作用域变量。原代码中result_string是main()函数的局部变量,无法被模块外部访问。 - 函数执行时机问题:
main()函数仅在直接运行sheetsReader.py时(if __name__ == "__main__"分支)才会执行,当作为模块导入时,该分支代码不会运行,导致result_string从未被赋值。
解决方案
方案1:让函数返回结果(最简方式)
修改sheetsReader.py,让main()返回处理后的字符串:
import os from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] def main(): credentials = None # 修复拼写错误:tocken.json → token.json if os.path.exists("token.json"): credentials = Credentials.from_authorized_user_file("token.json", SCOPES) if not credentials or not credentials.valid: if credentials and credentials.expired and credentials.refresh_token: credentials.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES) credentials = flow.run_local_server(port=0) with open("token.json","w") as token: token.write(credentials.to_json()) try: service = build("sheets", "v4", credentials=credentials) sheets = service.spreadsheets() # 替换SPREADSHEET_ID为实际表格ID result = sheets.values().get(spreadsheetId=SPREADSHEET_ID, range="Sheet1!A1:A9").execute() values = result.get("values", []) # 直接推导字符串,无需额外列表存储 result_string = ', '.join([row[0] for row in values]) return result_string except HttpError as error: print(error) return "" if __name__ == "__main__": main()
修改短信发送脚本,调用main()获取结果:
from datetime import datetime import Alert import time as tm import sheetsReader import schedule # 补充缺失的schedule导入 # 调用main函数获取字符串 text = sheetsReader.main() def job(): # 若需每日获取最新数据,建议在job内重新调用main() latest_text = sheetsReader.main() Alert.email_alert("todo", latest_text, "4807931338@vtext.com") # 修复schedule语法错误:day("7:20") → day.at("7:20") schedule.every().day.at("7:20").do(job) while True: schedule.run_pending() tm.sleep(1)
方案2:使用类封装(类似Java的面向对象写法)
如果习惯Java的类结构,可以将逻辑封装为类:
修改sheetsReader.py
import os from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError SCOPES = ["https://www.googleapis.com/auth/spreadsheets"] class SheetsReader: def __init__(self, spreadsheet_id): self.spreadsheet_id = spreadsheet_id self.credentials = self._get_credentials() def _get_credentials(self): credentials = None if os.path.exists("token.json"): credentials = Credentials.from_authorized_user_file("token.json", SCOPES) if not credentials or not credentials.valid: if credentials and credentials.expired and credentials.refresh_token: credentials.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES) credentials = flow.run_local_server(port=0) with open("token.json","w") as token: token.write(credentials.to_json()) return credentials def get_result_string(self, range_str="Sheet1!A1:A9"): try: service = build("sheets", "v4", credentials=self.credentials) sheets = service.spreadsheets() result = sheets.values().get(spreadsheetId=self.spreadsheet_id, range=range_str).execute() values = result.get("values", []) return ', '.join([row[0] for row in values]) except HttpError as error: print(error) return "" if __name__ == "__main__": reader = SheetsReader(SPREADSHEET_ID) print(reader.get_result_string())
修改短信发送脚本
from datetime import datetime import Alert import time as tm import sheetsReader import schedule # 初始化阅读器,传入实际表格ID reader = sheetsReader.SheetsReader(SPREADSHEET_ID) def job(): latest_text = reader.get_result_string() Alert.email_alert("todo", latest_text, "4807931338@vtext.com") schedule.every().day.at("7:20").do(job) while True: schedule.run_pending() tm.sleep(1)
内容的提问来源于stack exchange,提问作者Ivan Anderies
相关产品推荐
相关产品推荐

