将creds字典集成到Python脚本并封装Tkinter GUI时遇属性错误
问题解决与GUI封装方案
错误原因解析
触发AttributeError: 'dict' object has no attribute '__module__'的核心原因:你直接将credentials字典传给了需要Google OAuth2凭据对象的API方法,或是误用了初始化参数。gspread等库在读取本地JSON文件时用service_account_file参数,而嵌入字典时必须用service_account_info参数来生成合法的凭据对象。
完整解决代码与GUI封装
1. 嵌入Credentials字典
把原creds.json的内容直接转成Python字典:
CREDS_DICT = { "type": "service_account", "project_id": "你的项目ID", "private_key_id": "你的私钥ID", "private_key": "-----BEGIN PRIVATE KEY-----\n你的私钥内容\n-----END PRIVATE KEY-----\n", "client_email": "你的服务账号邮箱", "client_id": "你的客户端ID", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "你的证书URL" }
2. 正确初始化Google Sheets客户端
替换原有的文件读取方式,改用字典生成凭据:
import gspread from google.oauth2.service_account import Credentials # 定义权限范围 SCOPES = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"] def get_google_client(): try: creds = Credentials.from_service_account_info(CREDS_DICT, scopes=SCOPES) return gspread.authorize(creds) except Exception as e: raise RuntimeError(f"Google客户端初始化失败:{str(e)}")
3. Tkinter GUI完整封装
将爬取逻辑与界面结合,添加操作按钮和状态提示:
import tkinter as tk from tkinter import ttk, messagebox import gspread from google.oauth2.service_account import Credentials # 嵌入Credentials字典 CREDS_DICT = { # 替换为你的实际凭据内容 } SCOPES = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"] # 初始化Google客户端 def init_client(): try: creds = Credentials.from_service_account_info(CREDS_DICT, scopes=SCOPES) return gspread.authorize(creds) except Exception as e: messagebox.showerror("初始化失败", f"Google客户端连接出错:{str(e)}") return None # 爬取G League数据(替换为你的原有逻辑) def crawl_g_league(): # 示例数据,实际替换为你的爬取代码 return [["球员A", "G联盟X队", 21.3], ["球员B", "G联盟Y队", 19.7]] # 爬取国际球员数据(替换为你的原有逻辑) def crawl_international(): # 示例数据,实际替换为你的爬取代码 return [["球员C", "加拿大", 10.5], ["球员D", "澳大利亚", 9.2]] # 主执行函数 def run_crawl(): status_label.config(text="正在初始化客户端...") root.update_idletasks() client = init_client() if not client: status_label.config(text="初始化失败") return status_label.config(text="正在爬取数据...") root.update_idletasks() try: # 执行爬取 g_league_data = crawl_g_league() international_data = crawl_international() status_label.config(text="正在写入数据...") root.update_idletasks() # 写入G League数据到表格 sheet = client.open("球员数据汇总表").worksheet("G League") sheet.clear() sheet.update([["姓名", "球队", "场均得分"]] + g_league_data) # 写入国际球员数据到表格 sheet = client.open("球员数据汇总表").worksheet("国际球员") sheet.clear() sheet.update([["姓名", "国籍", "场均篮板"]] + international_data) status_label.config(text="操作完成!") messagebox.showinfo("成功", "所有数据已写入Google Sheets") except Exception as e: status_label.config(text="操作失败") messagebox.showerror("错误", f"爬取/写入出错:{str(e)}") # 构建GUI界面 root = tk.Tk() root.title("G联赛&国际球员数据爬取工具") root.geometry("450x220") main_frame = ttk.Frame(root, padding="25") main_frame.pack(fill=tk.BOTH, expand=True) title = ttk.Label(main_frame, text="球员数据爬取工具", font=("Arial", 15)) title.pack(pady=(0, 20)) crawl_btn = ttk.Button(main_frame, text="开始爬取并写入数据", command=run_crawl) crawl_btn.pack(pady=(0, 15)) status_label = ttk.Label(main_frame, text="等待操作...") status_label.pack() root.mainloop()
关键注意事项
CREDS_DICT中的private_key必须保留完整的换行符(\n),否则会导致凭据验证失败。- 替换示例中的爬取函数为你原有4个脚本的逻辑,确保数据格式符合Google Sheets的要求。
- 若仍出现类似错误,检查所有Google API相关的代码,确保没有直接传递字典给需要凭据对象的方法。
内容的提问来源于stack exchange,提问作者Anthony Madle
相关产品推荐
相关产品推荐

