我有一个问题,有时候python的google-drive-sdk没有检测到导出文档的结尾。它似乎认为谷歌文件是无限大小。
我正在开发自己的基于python的google-drive备份脚本(一个具有良好CLI界面的浏览器)。 git link for source code
它仍在制作中,目前只找到新文件并下载它们(使用'pull'命令)。
要执行最重要的google-drive命令,我按照官方google驱动器api教程下载媒体。 here
如果文档或文件是非google-docs文档,则会正确下载该文件。但是,当我尝试“导出”文件时。我看到我需要使用不同的mimeType。我有一本字典。
例如:我在导出文档时将application/vnd.google-apps.document
映射到application/vnd.openxmlformats-officedocument.wordprocessingml.document
。
从谷歌驱动器下载谷歌文档文件时,这似乎工作正常。我的意思是:我的代码status, done = downloader.next_chunk()
的while循环最终将done
设置为true
并完成下载。
但是,在某些文件中,done
标志永远不会到达true
,脚本将永久下载。这最终达到几Gb。也许我正在寻找错误的标志,表示文件在导出时已完成。我很惊讶谷歌驱动器永远不会抛出错误。有人知道是什么原因引起的吗?
目前我在我的代码中禁用了Google文档导出功能。
当我使用像“drive by rakyll”这样的脚本时(至少我拥有的版本)只需添加一个指向在线副本的链接。我真的想做一个正确的导出,以便我的离线系统可以维护驱动器上所有内容的完整备份。
P.S。为了其他人找到这个页面,可以使用“你应该使用这个服务而不是api”。我知道还有其他服务,但我真的希望探索与我自己的其他系统集成的drive-api功能。
答案 0 :(得分:2)
行。我在这里找到了伪解决方案。
问题是Google API永远不会返回Content-Length,而且响应是在Chunks中完成的。但是,返回的块是错误的,或者Python API无法正确处理它。
我做的是,抓住MediaIoBaseDownload
from here
我离开了所有地方,但改变了这一部分:
if 'content-range' in resp:
content_range = resp['content-range']
length = content_range.rsplit('/', 1)[1]
self._total_size = int(length)
elif 'content-length' in resp:
self._total_size = int(resp['content-length'])
else:
# PSEUDO BUG FIX: No content-length, no chunk info, cut the response here.
self._total_size = self._progress
最后else
是我添加的内容。我还通过设置DEFAULT_CHUNK_SIZE = 2*1024*1024
来更改默认的块大小。此外,您还必须从该文件中复制一些导入,包括此from googleapiclient.http import _retry_request, _should_retry_response
当然这不是一个解决方案,它只是说“如果我不理解响应,那就停在这里”。这可能会使一些导出无效,但至少它不会杀死服务器。这只是在我们找到一个好的解决方案之前。
<强>更新强>
此处已报告错误:https://github.com/google/google-api-python-client/issues/15
从2017年1月开始,唯一的解决方法是不使用MediaIoBaseDownload
而是执行此操作(不适合大文件):
req = service.files().export(fileId=file_id, mimeType=mimeType)
resp = req.execute(http=http)
答案 1 :(得分:0)
我正在使用它,并且可以在以下库中使用:
google-auth-oauthlib==0.4.1
google-api-python-client
google-auth-httplib2
这是我正在使用的代码段:
from apiclient import errors
from googleapiclient.http import MediaIoBaseDownload
from googleapiclient.discovery import build
def download_google_document_from_drive(self, file_id):
try:
request = self.service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print('Download %d%%.' % int(status.progress() * 100))
return fh
except Exception as e:
print('Error downloading file from Google Drive: %s' % e)
您可以将文件流写入文件:
import xlrd
workbook = xlrd.open_workbook(file_contents=fh.getvalue())