How to upload a file to Google Drive using a Python script? How to upload a file to Google Drive using a Python script? python python

How to upload a file to Google Drive using a Python script?


You can use the Documents List API to write a script that writes to Drive:

https://developers.google.com/google-apps/documents-list/

Both the Documents List API and the Drive API interact with the same resources (i.e. same documents and files).

This sample in the Python client library shows how to upload an unconverted file to Drive:

http://code.google.com/p/gdata-python-client/source/browse/samples/docs/docs_v3_example.py#180


The current documentation for saving a file to google drive using python can be found here:https://developers.google.com/drive/v3/web/manage-uploads

However, the way that the google drive api handles document storage and retrieval does not follow the same architecture as POSIX file systems. As a result, if you wish to preserve the hierarchical architecture of the nested files on your linux file system, you will need to write a lot of custom code so that the parent directories are preserved on google drive.

On top of that, google makes it difficult to gain write access to a normal drive account. Your permission scope must include the following link: https://www.googleapis.com/auth/drive and to obtain a token to access a user's normal account, that user must first join a group to provide access to non-reviewed apps. And any oauth token that is created has a limited shelf life.

However, if you obtain an access token, the following script should allow you to save any file on your local machine to the same (relative) path on google drive.

def migrate(file_path, access_token, drive_space='drive'):    '''        a method to save a posix file architecture to google drive    NOTE:   to write to a google drive account using a non-approved app,            the oauth2 grantee account must also join this google group            https://groups.google.com/forum/#!forum/risky-access-by-unreviewed-apps    :param file_path: string with path to local file     :param access_token: string with oauth2 access token grant to write to google drive    :param drive_space: string with name of space to write to (drive, appDataFolder, photos)    :return: string with id of file on google drive    '''# construct drive client    import httplib2    from googleapiclient import discovery    from oauth2client.client import AccessTokenCredentials    google_credentials = AccessTokenCredentials(access_token, 'my-user-agent/1.0')    google_http = httplib2.Http()    google_http = google_credentials.authorize(google_http)    google_drive = discovery.build('drive', 'v3', http=google_http)    drive_client = google_drive.files()# prepare file body    from googleapiclient.http import MediaFileUpload    media_body = MediaFileUpload(filename=file_path, resumable=True)# determine file modified time    import os    from datetime import datetime    modified_epoch = os.path.getmtime(file_path)    modified_time = datetime.utcfromtimestamp(modified_epoch).isoformat()# determine path segments    path_segments = file_path.split(os.sep)# construct upload kwargs    create_kwargs = {        'body': {            'name': path_segments.pop(),            'modifiedTime': modified_time        },        'media_body': media_body,        'fields': 'id'    }# walk through parent directories    parent_id = ''    if path_segments:    # construct query and creation arguments        walk_folders = True        folder_kwargs = {            'body': {                'name': '',                'mimeType' : 'application/vnd.google-apps.folder'            },            'fields': 'id'        }        query_kwargs = {            'spaces': drive_space,            'fields': 'files(id, parents)'        }        while path_segments:            folder_name = path_segments.pop(0)            folder_kwargs['body']['name'] = folder_name    # search for folder id in existing hierarchy            if walk_folders:                walk_query = "name = '%s'" % folder_name                if parent_id:                    walk_query += "and '%s' in parents" % parent_id                query_kwargs['q'] = walk_query                response = drive_client.list(**query_kwargs).execute()                file_list = response.get('files', [])            else:                file_list = []            if file_list:                parent_id = file_list[0].get('id')    # or create folder    # https://developers.google.com/drive/v3/web/folder            else:                if not parent_id:                    if drive_space == 'appDataFolder':                        folder_kwargs['body']['parents'] = [ drive_space ]                    else:                        del folder_kwargs['body']['parents']                else:                    folder_kwargs['body']['parents'] = [parent_id]                response = drive_client.create(**folder_kwargs).execute()                parent_id = response.get('id')                walk_folders = False# add parent id to file creation kwargs    if parent_id:        create_kwargs['body']['parents'] = [parent_id]    elif drive_space == 'appDataFolder':        create_kwargs['body']['parents'] = [drive_space] # send create request    file = drive_client.create(**create_kwargs).execute()    file_id = file.get('id')    return file_id

PS. I have modified this script from the labpack python module. There is class called driveClient in that module written by rcj1492 which handles saving, loading, searching and deleting files on google drive in a way that preserves the POSIX file system.

from labpack.storage.google.drive import driveClient


I found that PyDrive handles the Drive API elegantly, and it also has great documentation (especially walking the user through the authentication part).

EDIT: Combine that with the material on Automating pydrive verification process and Pydrive google drive automate authentication, and that makes for some great documentation to get things going. Hope it helps those who are confused about where to start.