Python 3.7调用Google Drive API v3修改文件权限遇写入字段报错
首先,咱们来拆解你遇到的问题:那个错误提示"The resource body includes fields which are not directly writable.",本质是因为你直接把permissions().get()返回的完整权限对象传给了update()方法。这个返回的权限对象里包含了很多API只读的字段(比如kind、id、etag、createdTime这些),API不允许在更新请求中携带这些字段,所以直接复用整个对象就会触发报错。
另外,我注意到你的核心需求是把公开文件设为私有,其实你之前尝试修改role的思路绕远路了——而且还有个逻辑问题:公开权限的type是"anyone",这种权限类型是不能被设置为"owner"的,owner角色只能分配给具体的用户或群组,不能是所有匿名用户。
下面给你两个针对性的解决方案:
方案1:正确的权限更新方式(如果确实需要修改角色)
如果你的场景真的需要修改某个合法权限的角色,不要复用get()返回的完整对象,只构造包含你要修改字段的极简请求体:
def actualizarPermisos(service, file_id, permission_id): try: # 只传递需要修改的字段,剔除所有只读属性 permission_body = {'role': 'writer'} return service.permissions().update( fileId=file_id, permissionId=permission_id, body=permission_body ).execute() except errors.HttpError as error: print(f'An error occurred: {error}') return None
注意:如果要将角色改为"owner",必须同时设置transferOwnership=True,而且你必须是文件的当前所有者,同时目标权限的type不能是"anyone"(比如得是具体的用户权限)。
方案2:直接删除公开权限(更贴合你的核心需求)
既然你的目标是把公开文件设为私有,最直接有效的方式是删除所有type为"anyone"的权限——这类权限就是让文件对所有人公开的原因,删除后文件就只会对所有者和指定授权用户开放:
def quitarAccesoPublico(service, file_id): try: # 获取文件的全部权限列表 permisos = service.permissions().list(fileId=file_id).execute() for permiso in permisos.get('permissions', []): # 筛选出公开权限(type为anyone) if permiso['type'] == 'anyone': # 删除该公开权限 service.permissions().delete( fileId=file_id, permissionId=permiso['id'] ).execute() print(f"已成功移除文件{file_id}的公开访问权限") return True except errors.HttpError as error: print(f'An error occurred: {error}') return False
这个方案不仅能解决你的报错问题,还能精准实现"将公开文件设为私有"的需求,比修改角色的思路更合理。
内容的提问来源于stack exchange,提问作者Julian Strah




