6
import hmac, base64, hashlib, urllib2
base = 'https://.......'

def makereq(key, secret, path, data):
    hash_data = path + chr(0) + data
    secret = base64.b64decode(secret)
    sha512 = hashlib.sha512
    hmac = str(hmac.new(secret, hash_data, sha512))

    header = {
        'User-Agent': 'My-First-test',
        'Rest-Key': key,
        'Rest-Sign': base64.b64encode(hmac),
        'Accept-encoding': 'GZIP',
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    return urllib2.Request(base + path, data, header)

Error: File "C:/Python27/btctest.py", line 8, in makereq hmac = str(hmac.new(secret, hash_data, sha512)) UnboundLocalError: local variable 'hmac' referenced before assignment

Somebody knows why? Thanks

user2480235
  • 61
  • 1
  • 1
  • 3
  • Writing `hmac = str(hmac.new(secret, hash_data, sha512))` means that the name `hmac` is reassigned locally (module names **do not** get a separate namespace, just like builtins; see e.g. https://stackoverflow.com/questions/6039605. Therefore, the code is trying to use `hmac.new` with the **local** `hmac` (**not** the global module), **before** it has been defined, as in the linked duplicate. – Karl Knechtel Feb 07 '23 at 01:44

2 Answers2

12

If you assign to a variable anywhere in a function, that variable will be treated as a local variable everywhere in that function. So you would see the same error with the following code:

foo = 2
def test():
    print foo
    foo = 3

In other words, you cannot access the global or external variable if there is a local variable in the function of the same name.

To fix this, just give your local variable hmac a different name:

def makereq(key, secret, path, data):
    hash_data = path + chr(0) + data
    secret = base64.b64decode(secret)
    sha512 = hashlib.sha512
    my_hmac = str(hmac.new(secret, hash_data, sha512))

    header = {
        'User-Agent': 'My-First-test',
        'Rest-Key': key,
        'Rest-Sign': base64.b64encode(my_hmac),
        'Accept-encoding': 'GZIP',
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    return urllib2.Request(base + path, data, header)

Note that this behavior can be changed by using the global or nonlocal keywords, but it doesn't seem like you would want to use those in your case.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
2

You are redefining the hmac variable within the function scope, so the global variable from the import statement isn't present within the function scope. Renaming the function-scope hmac variable should fix your problem.

Silas Ray
  • 25,682
  • 5
  • 48
  • 63