Python 3.x Google API,未定义名称io

Python 3.x Google API,未定义名称io,python-3.x,google-api,google-drive-api,Python 3.x,Google Api,Google Drive Api,因此,通过遵循GoogleDriveAPI文档,我试图创建一个程序,在GoogleDriver上查看所有保存的电子表格并下载它们 问题是我一直得到的名称“io”没有定义 from __future__ import print_function import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow

因此,通过遵循GoogleDriveAPI文档,我试图创建一个程序,在GoogleDriver上查看所有保存的电子表格并下载它们

问题是我一直得到的名称“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的Google api python客户端将Google电子表格作为XLSX文件下载。 如果我的理解是正确的,那么这个答案呢?请把这看作是几个答案中的一个

我认为,从您的错误消息中,可以发现授权过程已经完成,token.pickle已经创建,service.files.list已经工作。在这个回答中,我想是这样的。如果您还不能创建token.pickle文件,请再次检查

修改点: 关于未定义名称“io”的错误,请将导入io添加到脚本中。通过此操作,可以删除此错误消息。 但是在脚本中,有更多的修改点。因此,请检查以下几点

我认为在添加导入io后,出现了一个名为“MediaIoBaseDownload”的错误。因此,也请添加从GoogleAppClient.http导入MediaIoBaseDownload。 在添加import io和from GoogleAppClient.http import MediaIoBaseDownload时,我认为出现了身份验证作用域不足的错误。因此,请从中修改范围https://www.googleapis.com/auth/drive.metadata.readonly 到https://www.googleapis.com/auth/drive.readonly. 此时,请删除token.pickle文件,并通过运行脚本重新授权作用域。由此,新的范围得以体现。请小心这个。 如果您的Google驱动器中存在除Google电子表格以外的文件,我认为service.files.export_media会出错。如果只想检索Google电子表格,可以使用搜索查询。在您的情况下,可以使用q=mimeType='application/vnd.google apps.spreadsheet'。 在脚本中,使用fh=io.BytesIO。在这种情况下,文件作为导出文件下载。但下载的文件不是在您的电脑中创建的。例如,如果要在您的电脑中创建下载的文件,请将fh=io.BytesIO修改为fh=io.FileIOitem['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修改脚本。请小心这个。 在这种情况下,可能会有用。 如果在运行修改后的脚本时出错,请确认items=results.get'files',[]的items值。如果items为no value,则表示service.files.list不返回文件列表。 参考资料: 如果我误解了你的问题,而这不是你想要的结果,我道歉