Google API,未定义名称io

问题描述 投票:0回答:1

所以,通过遵循google drive API文档,我试图创建一个程序,该程序将在google driver上所有保存的电子表格中查找并下载。

问题是我一直没有得到名字'io'的定义

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

    # Call the Drive v3 API
    results = service.files().list(
        pageSize=10, fields="nextPageToken, files(id, name)").execute()
    items = results.get('files', [])

    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1})'.format(item['name'], item['id']))
            file_id = item['id']
            request = service.files().export_media(fileId=file_id,
                                                        mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
            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))

if __name__ == '__main__':
    main()

所以...我在做什么错?

python-3.x google-api google-drive-api
1个回答
0
投票
  • 您想使用带有python的google-api-python-client将Google Spreadsheet下载为XLSX文件。

如果我的理解是正确的,那么这个答案怎么样?请认为这只是几个答案之一。

我认为从您的错误消息中可以发现,授权过程已完成,token.pickle已创建且service.files().list()有效。在这个答案中,我想是这样。如果您仍无法创建token.pickle文件,请再次检查the Quickstart

修改点:

  • 关于name 'io' is not defined的错误,请在脚本中添加import io。这样,可以删除此错误消息。

但是在您的脚本中,还有更多修改点。因此,请检查以下几点。

  • 我认为在添加import io之后,会出现name 'MediaIoBaseDownload' is not defined错误。所以也请添加from googleapiclient.http import MediaIoBaseDownload
  • 当添加import iofrom googleapiclient.http import MediaIoBaseDownload时,我认为发生了insufficient authentication scopes错误。因此,请将范围从https://www.googleapis.com/auth/drive.metadata.readonly修改为https://www.googleapis.com/auth/drive.readonly
    • 目前,请删除token.pickle文件,然后通过运行脚本重新授权范围。由此,反映了新的范围。请注意这一点。
  • [如果您的Google云端硬盘中有除Google Spreadsheet以外的文件,我认为service.files().export_media()发生了错误。当您只想检索Google Spreadsheet时,可以使用搜索查询。根据您的情况,可以使用q="mimeType='application/vnd.google-apps.spreadsheet'"
  • 在您的脚本中,使用fh = io.BytesIO()。在这种情况下,文件将作为导出下载。但是下载的文件未在您的PC中创建。例如,如果要将下载的文件创建到PC上,请将fh = io.BytesIO()修改为fh = io.FileIO(item['name'] + '.xlsx', mode='wb')

当以上修改点反映到您的脚本时,它变成如下。

修改的脚本:

[在运行脚本之前,请删除token.pickle的文件。这样,在运行脚本时,将运行授权过程,完成授权后,新的作用域将反映到访问中令牌和刷新令牌。

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

import io  # Added
from googleapiclient.http import MediaIoBaseDownload  # Added

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']  # Modified

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

    # Call the Drive v3 API
    results = service.files().list(
        pageSize=10, fields="nextPageToken, files(id, name)", q="mimeType='application/vnd.google-apps.spreadsheet'").execute()  # Modified
    items = results.get('files', [])

    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1})'.format(item['name'], item['id']))
            file_id = item['id']
            request = service.files().export_media(fileId=file_id,
                                                        mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
            # fh = io.BytesIO()
            fh = io.FileIO(item['name'] + '.xlsx', mode='wb')  # If you want to create the downloaded file to your PC, please use this instead of "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))

if __name__ == '__main__':
    main()

注意:

  • 如果要下载10个以上的文件,请修改pageSize=10。最大值为1000。如果要下载的文件超过1000,则需要使用pageToken修改脚本。请注意这一点。
  • 如果运行修改后的脚本时发生错误,请确认itemsitems = results.get('files', [])的值。 items没有值时,表示service.files().list()不返回文件列表。

参考:

如果我误解了您的问题,而这不是您想要的结果,我深表歉意。

© www.soinside.com 2019 - 2024. All rights reserved.