UnboundLocalError issue using Python Dropbox API

Question:

I am trying to create a class in python which reads the access key/secret for dropbox and then downloads a file. The key/secret part is working alright, but I seem to be having a problem recognizing the client object, probably due to an issue with global vs local variables. I can’t find my answer anywhere else.

Here’s part of my code:

from dropbox import client, rest, session

class GetFile(object):

    def __init__(self, file1):
        self.auth_user()

    def auth_user(self):
        APP_KEY = 'xxxxxxxxxxxxxx'
        APP_SECRET = 'xxxxxxxxxxxxxx'
        ACCESS_TYPE = 'dropbox'
        TOKENS = 'dropbox_token.txt'

        token_file = open(TOKENS)
        token_key,token_secret = token_file.read().split('|')
        token_file.close()

        sess = session.DropboxSession(APP_KEY,APP_SECRET, ACCESS_TYPE)
        sess.set_token(token_key,token_secret)
        client = client.DropboxClient(sess)

        base, ext = file1.split('.')

        f, metadata = client.get_file_and_metadata(file1)
        out = open('/%s_COPY.%s' %(base, ext), 'w')
        out.write(f.read())

And here’s the error:

Traceback (most recent call last):
File "access_db.py", line 30, in <module>
start = GetFile(file_name)
File "access_db.py", line 6, in __init__
self.auth_user()
File "access_db.py", line 20, in auth_user
client = client.DropboxClient(sess)
UnboundLocalError: local variable 'client' referenced before assignment

I’m new-ish to python so let me know if there are other obvious things I may be doing wrong.

Asked By: hobs2376

||

Answers:

You imported the dropbox.client module into a your module scope as client, but you also have a local variable client in your .auth_user() method.

When python sees an assignment (such as client =) in a function when compiling, it marks that name as a local variable. At this point your import of the client module is doomed, it is no longer visible in your function under that name.

Next, in python’s eyes you are trying to access that local variable client in the function; you are trying to get the attribute DropboxClient from it, but you haven’t yet assigned anything to the variable client at that moment. So the UnboundLocal exception is thrown.

The workaround is to either not use client as a local variable, to import the top-level dropbox module instead of it’s submodules, then refer to it’s submodules with the full dropbox.client, etc. paths, or thirdly, by giving the client module a new name:

  1. Don’t use client as a local:

    dbclient = client.DropboxClient(sess)
    # ...
    f, metadata = dbclient.get_file_and_metadata(file1)
    
  2. Import the dropbox module directly:

    import dropbox
    # ...
    
        sess = dropbox.session.DropboxSession(APP_KEY,APP_SECRET, ACCESS_TYPE)
        # ...
        client = dropbox.client.DropboxClient(sess)
    
  3. Provide an alias for the client module:

    from dropbox import session, rest
    from dropbox import client as dbclient
    # ...
    
        client = dbclient.DropboxClient(sess)
    
Answered By: Martijn Pieters
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.