You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python服务账号调用Blogger/Google API时出现OSError错误

解决Blogger API服务账号认证时的OSError: Errno 9 Bad file descriptor错误

问题分析

在Debian系统使用google-api-python-client 2.65.0,通过服务账号JSON密钥访问Blogger API时,调用googleapiclient.discovery.build()触发OSError: [Errno 9] Bad file descriptor错误。已确认凭证读取正常,浏览器可访问API发现文档,但代码执行失败,报错根源在底层socket发送数据时出现无效文件描述符。

核心原因及解决方案

1. 混用新旧OAuth2凭证库导致冲突

代码同时导入了已弃用的oauth2client库和官方推荐的google-oauth2库,两者在HTTP请求处理的底层逻辑存在冲突,可能导致socket资源异常。

修复操作:
完全替换oauth2client的使用,改用google.oauth2.service_account生成凭证:

# 删除旧的oauth2client导入
# from oauth2client import client
# from oauth2client.service_account import ServiceAccountCredentials

# 替换为google官方新库
from google.oauth2 import service_account

生成凭证的代码修改为:

credentials = service_account.Credentials.from_json_keyfile_dict(
    key_dict,
    scopes=SCOPES
)
# 如果需要模拟博客所有者访问(部分Blogger接口要求),添加subject参数
# credentials = credentials.with_subject("your-blog-owner-email@example.com")

2. httplib2版本过旧

报错中使用的httplib2版本为0.10.3,该版本存在与新版google-api-python-client不兼容的网络请求bug,会导致socket描述符异常。

修复操作:
升级httplib2到最新兼容版本:

pip install --upgrade httplib2

3. 网络/代理配置问题

虽然浏览器能访问API地址,但Python进程可能使用了不同的代理配置,或者系统socket资源被异常占用。

排查操作:

  • 在终端测试Python能否访问API发现文档:
import urllib.request
response = urllib.request.urlopen("https://www.googleapis.com/discovery/v1/apis/blogger/v3/rest")
print(response.status)
  • 如果使用代理,确保Python进程的环境变量(HTTP_PROXY/HTTPS_PROXY)配置正确,或者在代码中显式设置代理:
from googleapiclient.discovery import build
import httplib2

http = httplib2.Http(proxy_info=httplib2.ProxyInfo(
    httplib2.socks.PROXY_TYPE_HTTP, 
    "proxy-host", 
    8080
))
service = build('blogger', 'v3', credentials=credentials, http=http, static_discovery=False)

修改后的完整代码示例

import json
from google.oauth2 import service_account
import googleapiclient.discovery

SCOPES = ['https://www.googleapis.com/auth/blogger']

def get_key_dict():
    SERVICE_ACCOUNT_FILE = '/path/to/myproject/apis/blogger/private_secrets.json'
    with open(SERVICE_ACCOUNT_FILE, 'r') as keyfile:
        return json.load(keyfile)

key_dict = get_key_dict()
credentials = service_account.Credentials.from_json_keyfile_dict(key_dict, scopes=SCOPES)
# 如果需要模拟特定用户访问,取消注释并替换邮箱
# credentials = credentials.with_subject("blog-owner@example.com")

service = googleapiclient.discovery.build('blogger', 'v3', credentials=credentials, static_discovery=False)

try:
    users = service.users()
    thisuser = users.get(userId="self").execute()
    print(f"This user's display name is: {thisuser['displayName']}")

    blogs = service.blogs()
    thisusersblogs = blogs.listByUser(userId="self").execute()
    for blog in thisusersblogs["items"]:
        print(f"The blog named '{blog['name']}' is at: {blog['url']}")

    posts = service.posts()
    for blog in thisusersblogs["items"]:
        print(f"The posts for {blog['name']}:")
        request = posts.list(blogId=blog["id"])
        while request is not None:
            posts_doc = request.execute()
            if "items" in posts_doc and posts_doc["items"]:
                for post in posts_doc["items"]:
                    print(f"  {post['title']} ({post['url']})")
            request = posts.list_next(request, posts_doc)

except Exception as e:
    print(f"Error occurred: {str(e)}")

内容的提问来源于stack exchange,提问作者madtyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 04:35:44