No se puede cargar un archivo enorme en Google Drive usando Python

Estoy intentando cargar archivos en el disco de Google mediante la API de Google usando el siguiente código

import httplib2 from apiclient import discovery from httplib2 import Http from oauth2client import file, client, tools try: import argparse flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args() except ImportError: flags = None SCOPES =['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/drive.file','https://www.googleapis.com/auth/drive.appdata', 'https://www.googleapis.com/auth/drive.apps.readonly'] store = file.Storage('scope.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('client_secret.json', SCOPES) creds = tools.run_flow(flow, store, flags) if flags else tools.run(flow, store) DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http())) else: credentials = creds http = credentials.authorize(httplib2.Http()) DRIVE = discovery.build('drive', 'v3', http=http) FILES = ( ('/home/vkm/mayur/Demo_Google_API.zip', 'application/vmd.google-apps.document'), ) for filename, mimeType in FILES: metadata = {'name': filename} if mimeType: metadata['mimeType'] = mimeType res = DRIVE.files().create(body=metadata, media_body=filename).execute() if res: print('Uploaded "%s" (%s)' % (filename, res['mimeType'])) 

Puedo cargar los archivos pequeños, pero cuando estoy probando con 8GB del archivo, me está dando MemorryErro. ​​Por favor, encuentre el mensaje de error que estoy recibiendo.

 Traceback (most recent call last): File "demo.py", line 46, in  res = DRIVE.files().create(body=metadata, media_body=filename).execute() File "/usr/local/lib/python2.7/dist-packages/googleapiclient/discovery.py", line 853, in method payload = media_upload.getbytes(0, media_upload.size()) File "/usr/local/lib/python2.7/dist-packages/googleapiclient/http.py", line 482, in getbytes return self._fd.read(length) MemoryError 

El comentario de Vikram reveló un problema en la respuesta de next_chunk : next_chunk debe llamarse al valor de retorno de:

 request = DRIVE.files().create(body=metadata, media_body=media) 

no en el valor de retorno de request.execute() .

Aquí hay un fragmento de código de Python que verifiqué al trabajar en archivos de hasta 10 MB en mi cuenta de Google Drive:

 # Upload some file that just happens to be binary (we # don't care about metadata, just upload it without # translation): the_file_to_upload = 'some_binary_file' metadata = {'name': the_file_to_upload} # Note the chunksize restrictions given in # https://developers.google.com/api-client-library/python/guide/media_upload media = MediaFileUpload(the_file_to_upload, chunksize=1024 * 1024, # Not sure whether or not this mimetypes is necessary: mimetype='text/plain', resumble=True) request = drive_service.files().create(body=metadata, media_body=media) response = None while response is None: status, response = request.next_chunk() if status: print("Uploaded %d%%." % int(status.progress() * 100)) print("Upload of {} is complete.".format(the_file_to_upload)) 

Aquí hay un fragmento de código de Python que descarga el mismo archivo, pero en un archivo diferente, para que pueda usar sha1sum para verificar que Google Drive no haya alterado el archivo al entrar y salir.

 # Verify downloading works without translation: request = drive_service.files().get_media(fileId=response['id']) # Use io.FileIO. Refer to: # https://google.github.io/google-api-python-client/docs/epy/googleapiclient.http.MediaIoBaseDownload-class.html out_filename = the_file_to_upload + ".out" fh = io.FileIO(out_filename, mode='wb') downloader = MediaIoBaseDownload(fh, request, chunksize=1024 * 1024) done = False while done is False: status, done = downloader.next_chunk() if status: print("Download %d%%." % int(status.progress() * 100)) print("Download Complete!") 

Puede cargar el archivo utilizando una carga de medios reanudable . Esto enviará el archivo en trozos y no debería agotar su memoria, lo que supongo que está sucediendo porque su cliente está intentando enviar todo el archivo a la vez.

Para hacer esto, debe pasar un objeto MediaFileUpload al método create() en el que el indicador de resumble se establece en True . Opcionalmente también puede establecer el chunksize .

 metadata = {'name': filename} media = MediaFileUpload(filename, mimetype=mimetype, resumble=True) request = DRIVE.files().create(body=metadata, media_body=media) response = None while response is None: status, response = request.next_chunk() if status: print "Uploaded %d%%." % int(status.progress() * 100) print "Upload Complete!" 

Intente reducir el chunksize del chunksize si es necesario.