0

I am trying to understand why this function call to download_file() keeps throwing an error. Can someone help me understand why this is the case?

'''

def get_files():
    results = service.files().list(
        pageSize=10, fields="nextPageToken, files(id, name, mimeType)").execute()
    items = results.get('files', [])
    return items

def download_file(id, filename, mimeType):
    file_id = id
    request = get_files()

    fh = io.FileIO(filename, 'wb')
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download {}%.".format(int(status.progress() * 100)))
        print("Done")
    return fh.getvalue()

def download_all_files():
    files = get_files()
    for file in files:
        id = file['id']
        name = file['name']
        the_type = file['mimeType']
        #print(file['id'], file['name'], file['mimeType'])
        download_file(id, name, the_type)

#Calls
download_all_files()

'''

AttributeError: 'list' object has no attribute 'uri'

  • On which line in this code does the error occur? – Solvalou Dec 10 '19 at 19:29
  • Can you include the whole error message? – user1558604 Dec 10 '19 at 19:34
  • File "gsuitebackup.py", line 82, in main() File "gsuitebackup.py", line 75, in main download_all_files() File "gsuitebackup.py", line 72, in download_all_files download_file(id, name, the_type) File "gsuitebackup.py", line 57, in download_file downloader = MediaIoBaseDownload(fh, request) File "path", line 130, in positional_wrapper return wrapped(*args, **kwargs) File "path", line 647, in __init__ self._uri = request.uri AttributeError: 'list' object has no attribute 'uri' – hexstonedev Dec 10 '19 at 19:52
  • I can run that print statement in the download all files function and I get all of the right values, so I am just not sure why they are not plugging into function correctly. – hexstonedev Dec 10 '19 at 19:54
  • Can I ask you about your question? 1. Do you want to download files from your Google Drive? Unfortunately, I couldn't understand about your goal from your script. 2. If my understanding is correct, what mimeTypes of files do you want to download? 3. Have you already been able to use Drive API? – Tanaike Dec 10 '19 at 22:54
  • Yes, I got it working now. I was trying to download regular files and export google app files so that I could back them up on a local server. I have completed this part of the task for now, but I will keep in mind to make sure I give more context to the situation in the future. Thanks. – hexstonedev Dec 11 '19 at 13:41

1 Answers1

1

The error you are having:

AttributeError: 'list' object has no attribute 'uri'

Is caused because you are passing a list object to the MediaIoBaseDownload when in the documentation for such object it specifies that the the second parameter should be a googleapiclient.http.HttpRequest.

Also you are calling the function get_files() two times, one to iterate to every file and the other to actually get the request variable (which doesn't make much sense).

In the google documentation there is an example to actually download a file from Google Drive. In that example the python code looks like (python 2 code):

file_id = '0BwwA4oUTeiV1UVNwOHItT0xfa2M'
request = drive_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)

See that here in the example they are invoking the get_media() method instead of the list of files that you are passing as input.

So based in that I would change your download_file function too look something like this:


def download_file(id, filename, mimeType):
    file_id = id
    request = drive_service.files().get_media(fileId=id)

    fh = io.FileIO(filename, 'wb')
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download {}%.".format(int(status.progress() * 100)))
        print("Done")
    return fh.getvalue()

Just as a note I would like to also mention that id is actually a built in function of python. So you shouldn't be using it as variable name

Raserhin
  • 2,516
  • 1
  • 10
  • 14
  • Thank you. Yeah, I did get it by changing the download_file() method. Also thank you for the tip about 'id', I will use that in the future. – hexstonedev Dec 11 '19 at 13:38