我通过pydrive使用Google Drive API在两个Google云端硬盘帐户之间移动文件。我一直在测试一个包含16个文件的文件夹。我的代码总是在第六个文件中引发错误
"超出用户费率限制">
我知道请求数量有限制(10 / s或1000 / 100s),但我已尝试使用Google Drive API建议的exponential backoff来处理此错误。即使在248秒之后,它仍然会引发同样的错误。
这是我正在做的一个例子
def MoveToFolder(self,files,folder_id,drive):
total_files = len(files)
for cont in range(total_files):
success = False
n=0
while not success:
try:
drive.auth.service.files().copy(fileId=files[cont]['id'],
body={"parents": [{"kind": "drive#fileLink", "id": folder_id}]}).execute()
time.sleep(random.randint(0,1000)/1000)
success = True
except:
wait = (2**n) + (random.randint(0,1000)/1000)
time.sleep(wait)
success = False
n += 1
我尝试使用"批处理请求"复制文件,但它会为10个文件引发相同的错误。
def MoveToFolderBatch(self,files,folder_id,drive):
cont=0
batch = drive.auth.service.new_batch_http_request()
for file in files:
cont+=1
batch.add(drive.auth.service.files().copy(fileId=file['id'],
body={"parents": [
{"kind": "drive#fileLink", "id": folder_id}]}))
batch.execute()
有没有人有任何提示?
编辑: 根据谷歌的支持:
关于超出用户速率限制错误,与控制台中设置的每用户速率限制完全无关。相反,它来自Drive API依赖的内部Google系统,并且最有可能在单个帐户拥有域中的所有文件时发生。 我们不建议单个帐户拥有所有文件,而是让域中的个人用户拥有这些文件。要传输文件,您可以查看此链接。另外,请检查建议上的此链接以避免错误。
答案 0 :(得分:2)
403: User Rate Limit Exceeded基本上是防洪保护。
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "userRateLimitExceeded",
"message": "User Rate Limit Exceeded"
}
],
"code": 403,
"message": "User Rate Limit Exceeded"
}
}
你需要放慢速度。正如您所做的那样实施指数退避是正确的行动方案。
谷歌在计算请求时并不完美,因此自己计算这些请求实际上并没有帮助。有时你可以在第二次获得15次请求时,你只能获得7次。
您还应该记住,如果服务器上有很多负载,您正在与使用服务器的其他人一起完成您的一个请求可能需要更长时间,而另一个可能不需要。不要在大多数人设置提取的cron作业的时候运行。
注意:如果你去google开发者控制台,你已经启用了驱动程序API到达配额选项卡,请点击
旁边的铅笔图标每个用户每100秒查询
和
每100秒查询
你可以增加它们。一个是基于用户,另一个是基于项目。每个用户可以在100秒内发出X请求,您的项目可以每100秒发出Y请求。
注意:不知道你可以设置多高。这是我的开发帐户,因此它可能有一些我无法记住的测试版访问权。
答案 1 :(得分:2)
请参阅403 rate limit after only 1 insert per second和403 rate limit on insert sometimes succeeds
关键点是: -
退避,但不实施指数退避!。这将简单地终止您的应用程序吞吐量
相反,您需要主动限制您的请求以避免304发生。在我的测试中,我发现每1.5秒最大可持续吞吐量约为1次。
批处理会使问题变得更糟,因为批次在304引发之前被解压缩。 IE浏览器。一批10个被解释为10个快速交易,而非1个。
尝试此算法
delay=0 // start with no backoff
while (haveFilesInUploadQueue) {
sleep(delay) // backoff
upload(file) // try the upload
if (403 Rate Limit) { // if rejected with a rate limit
delay += 2s // add 2s to delay to guarantee the next attempt will be OK
} else {
removeFileFromQueue(file) // if not rejected, mark file as done
if (delay > 0) { // if we are currently backing off
delay -= 0.2s // reduce the backoff delay
}
}
}
// You can play with the 2s and 0.2s to optimise throughput. The key is to do all you can to avoid the 403's
有一点需要注意的是,驱动器中存在(是?)错误,有时上传会被403拒绝,但是,尽管发送了403,但驱动器继续创建文件。症状将是重复的文件。所以为了更加安全,在403之后你应该以某种方式检查文件是否真的存在。最简单的方法是使用预先分配的ID,或者将自己的不透明ID添加到属性中。