簡體   English   中英

谷歌驅動python api:導出永遠不會完成。

[英]Google drive python api: export never completes.

總結:

我有一個問題,有時用於 python 的 google-drive-sdk 沒有檢測到正在導出的文檔的結尾。 似乎認為 google 文檔是無限大的。

我遵循的背景、源代碼和教程:

我正在開發我自己的基於 python 的 google-drive 備份腳本(一個帶有用於瀏覽的漂亮 CLI 界面的腳本)。 源代碼的 git 鏈接

它仍在制作中,目前只能找到新文件並下載它們(使用“pull”命令)。

為了執行最重要的 google-drive 命令,我按照官方 google drive api 教程下載媒體。 這里

什么工作:

當文檔或文件是非 google-docs 文檔時,該文件會被正確下載。 但是,當我嘗試“導出”文件時。 我發現我需要使用不同的 mimeType。 我有一本字典。

例如:我在導出文檔時將application/vnd.google-apps.documentapplication/vnd.openxmlformats-officedocument.wordprocessingml.document

從谷歌驅動器下載谷歌文檔時,這似乎工作正常。 我的意思是:我的 while 循環代碼status, done = downloader.next_chunk()最終將done設置為true並且下載完成。

什么不起作用:

但是,在某些文件上, done標志永遠不會變為true ,腳本將永遠下載。 這最終達到幾個 Gb。 也許我正在尋找錯誤的標志,表明在進行導出時文件已完成。 我很驚訝 google-drive 永遠不會拋出錯誤。 有誰知道這可能導致什么?

當前狀態

現在我在我的代碼中禁用了谷歌文檔的導出。

當我使用諸如“由 rakyll 驅動”(至少是我擁有的版本)之類的腳本時,只會放置一個指向在線副本的鏈接。 我真的很想進行適當的導出,以便我的離線系統可以維護驅動器上所有內容的完整備份。

Ps 為了其他人找到這個頁面,寫“你應該使用這個服務而不是api”是可以的。 我知道還有其他服務可用於此目的,但我真的很想探索驅動器 API 功能以與我自己的其他系統集成。

好的。 我在這里找到了一個偽解決方案。

問題是 Google API 從不返回 Content-Length 並且響應是在 Chunks 中完成的。 但是,要么返回的塊是錯誤的,要么 Python API 無法正確處理它。

我所做的是, 從這里獲取MediaIoBaseDownload的代碼

我保持不變,但改變了這一部分:

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)

我正在使用它,它適用於以下庫:

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())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM