Python: Help with UnboundLocalError: local variable referenced before assignment - python

I keep getting this error for a portion of my code.
Traceback (most recent call last):
File "./mang.py", line 1688, in <module>
files, tsize = logger()
File "./mang.py", line 1466, in logger
nl = sshfile(list, "nl")
UnboundLocalError: local variable 'sshfile' referenced before assignment
I haven't put the code up cause it goes back and forth between functions. I'm wondering if anyone could tell me why python is spitting this error? sshfile is not a variable it's a class.

You probably haven't imported the file which contains the definition of sshfile, or you need to qualify the class name with the package name. It depends on how you imported it.
What package does it come from? Where is it defined?
Update
For anyone else reading this, after a discussion in the comments it turned out that the problem was that the name sshfile had been used further down in the function as a variable name, like this:
class sshfile:
pass
def a():
f = sshfile() # UnboundLocalError here
sshfile = 0
a()
The solution is to not use a variable name that hides a class name that you need to use.

Related

Global variable not acting very globally

So I have the following module named examplemod:
def maybeglobal():
global test
test = [1, 2, 3]
I then import the module and run the function:
import examplemod
examplemod.maybeglobal()
When I try to reference the new (supposedly) global variable test, I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'test' is not defined
I'm running 2.6.6 and have been currently banging my head into a wall for about two hours now. Do I just not understand how global is supposed to work? Because I'm pretty sure this is exactly what global is for.
Also, before people get at me for using global variables, the whole purpose of the function I'm working on is to have the custom class object that a module function creates accessible to the user for manipulation.
It's global at the module level. So you need to do examplemod.test and you will get your expected answer.

How to add a global symbol that can be bound by Python compiler?

This is my first question so please be nice :) I am rather new to Python but I am very experienced in other programming languages (e.g. C++).
UPDATE 2 - Solution Found
Thanks everyone for helping :) As the solution is "hidden" in comments I will repost it here.
Instead of
file_symbols = {}
the variable local_symbol must initially be added to the file_symbols dictionary:
file_symbols = { "local_symbol" : local_symbol }
For anyone reading this: all variable / class names posted here are not to be understood as actual useful names as these examples are synthetic in nature ;)
Well... now I have to figure out the FULL meaning of:
exec compiled_code in file_symbols
So far I thought it would do nothing more than updating the dictionary file_symbols with the symbols found in compiled_code.
But it actually does a bit more as it seems! :)
UPDATE 1
Ok, my sample project below seems to be too simple to show the actual problem. Anyway, thanks for your already provided support! :)
In fact I want to first compile multiple *.py files which need access to a local symbol (class instance). All symbols coming from these compiled files shall be collected and then be used as an environment for OTHER code objects.
So I really need to do this
(note the following code shows the concept, not actual executable code):
class Functions:
(...)
global_symbols = {}
local_symbol = Functions()
# note that the external files need to access local_symbol to call its functions!
for file in external_files:
code = file.load()
compiled_code = compile(code, "<string>", "exec")
file_symbols = {}
exec compiled_code in file_symbols
global_symbols.update(file_symbols)
some_code = another_file.load()
compiled_code = compile(some_code, "<string>", "exec")
exec(compiled_code, global_symbols)
In this example the line
exec compiled_code in file_symbols
produces a NameError() - because there is no way they could access local_symbol as it is not defined anywhere in the external files although it shall be used!
So the question is how to provide access to local_symbol for the external_files so that they can call the instance's functions??
My import hook solution that some of you regard as "hack" was the only working solution so far. I would love to use a simpler one if there is any!
Thanks again :)
My initial question was this:
So here we go. What I intend to do is advanced stuff and I did not find a solution to my problem neither here nor anywhere else.
Assume the following code in Python (2.6.x / 2.7.x):
class Functions:
def __init__(self):
(...)
def func_1(...):
(...)
def func_2(...):
(...)
(...)
def func_n(...):
(...)
functions = Functions()
code = loadSomeFile(...)
compiled_code = compile(code, "<string>", "exec")
(...)
global_env = {}
local_env = {"func":functions}
exec(compiled_code, global_env, local_env)
where code in the example above is loaded from a file with a content that might look like this:
import something
(...)
def aFunction(...):
a = func.func_1(...)
b = func.func_2(...)
return a * b
(...)
aFunction()
Please note that (...) in the code above means that there might be more code that I left out for the sake of simplicity.
The problem I encounter in my example is that the compiler raises an error for this line:
compiled_code = compile(code, "<string>", "exec")
I will get this error: NameError("global name 'func' is not defined")
This error is totally understandable as the compiler can't bind to any global symbol with the name "func". But I still want to compile the code this way.
So the obvious question is:
How can I define global symbols that can be used by the compiler for compile() statements so that the compiler will bind any "unknown" symbol to an object of my choice?
In my example I would like to define a global symbol func that is bound to an instance of class Functions so that the compiler will find this symbol when compiling code which makes use of func as seen in the example above.
So how can this be accomplished?
Important:
Please note that I am aware that directly executing the code using exec(...) would fix the compilation problem because the dict local_env in the example above would provide the symbol that is required for successful execution. HOWEVER I can't do it this way because the code that shall be compiled is not small at all. It might consist of hundreds of code lines and this code is also not executed only once but many many times.
So for performance reasons I really need to compile the code rather than directly executing it.
Thanks for helping me :)
Don't provide separate globals and locals dicts to exec. That causes the executed code to behave as if it's embedded in a class definition. That means that any variable lookups in functions defined in the executed code bypass locals.
>>> exec("""
... def f():
... print a
... f()""", {}, {"a": 3})
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
File "<string>", line 4, in <module>
File "<string>", line 3, in f
NameError: global name 'a' is not defined
>>> exec("""
... def f():
... print a
... f()""", {"a": 3})
3
Just pass a globals dict.
The simple explanation is that you pass in func in the local namespace. aFunction does not have access to the locals you passed in (it has its own locals). All aFunction has access to is its own locals and its module's globals. func is in neither of these and so the function call fails.
Most normal modules work with their globals and locals as the same namespace (you can check this out yourself assert globals() is locals()). This is why you can define things at the module level and have them available to any defined functions (all names in a module are automatically global).
To make this work you need to make locals and globals the same dict, or just not pass locals at all. If you don't want globals to be mutated, then just copy globals and then add func to it.
src = """
def aFunction():
a = func.func_1()
b = func.func_2()
return a + b
value = aFunction()
"""
class Functions:
def func_1(self):
return "first"
def func_2(self):
return "second"
functions = Functions()
compiled_code = compile(src, "<string>", "exec")
global_env = {}
local_env = {"func":functions}
namespace = dict(global_env)
namespace.update(local_env)
exec(compiled_code, namespace)
print(namespace["value"])
it is an interesting question, thanks for posting it. I've been taking a look at how to change the globals table in compile time. Apparently, you can call the __import__() function directly and:
pass your globals in order to determine how to interpret the name in a package context.
Source: Package documentation
Well, obviously it works by simply adding (and potentially removing - if using multiple "func" instances) the instance to sys.modules:
sys.modules["func"] = functions
(...)
compiled_code = compile(code, "<string>", "exec")
The complete and working solution including an importer hook (which intercepts "import func" lines in source code files) would look like this:
import sys
class Functions:
def __init__(self):
(...)
def func_1(...):
(...)
def func_2(...):
(...)
(...)
def func_n(...):
(...)
functions = Functions()
code = loadSomeFile(...)
hook_name = "func"
class ImporterHook:
def __init__(self, path):
if path != hook_name:
raise ImportError()
def find_module(self, fullname, path=None):
return self
def load_module(self, path):
if sys.modules.has_key(path):
return sys.modules[path]
else:
sys.modules[path] = functions
return functions
sys.path_hooks.append(ImporterHook)
sys.path.insert(0, hook_name)
compiled_code = compile(code, "<string>", "exec")
(...)
exec(compiled_code)
Not so hard as it seems :) For more information see here:
https://www.python.org/dev/peps/pep-0302/#specification-part-2-registering-hooks
and here:
https://pymotw.com/2/sys/imports.html
THANKS :)

Intercepting global name lookup in a Python exec environment

I realize that this may be a fragile approach, but I'm looking for a way to intercept global name lookups (and also to provide a value/binding when the lookup fails) under 'exec'.
Use case: I want to provide a restricted execution environment for some external scripts written by users. I am trying to tailor the script conventions and namespace construction to very unsophisticated users, so I'd like them to be able to call a bunch of functions as if they were "global" without having to construct the entire dictionary by hand ahead of time.
Ergo, I'd like to intercept the global/module namespace lookup of SomeIdentifierNameTheyMayUse, and to dynamically bind that name to something computed rather than something already bound in the namespace.
Is something like this possible in general?
I managed to get something sort-of working, but it has problems, as you can see below:
class mydict( dict ):
def __missing__( self, key ):
print "__missing__:", key
return 99
d = mydict()
d[ '__builtins__' ] = {}
code = """
# triggers __missing__ call as desired, prints 99
print this_bad_sym_is_ok
def action1():
print 'action1!'
# does not trigger __missing__. Why? And how can I fix it?
print this_bad_sym_is_not
"""
exec code in d
print "d=", d
exec 'action1()' in d
which currently produces:
__missing__: this_bad_sym_is_ok
99
d= {'__builtins__': {}, 'action1': <function action1 at 0x107d6b2a8>}
action1!
Traceback (most recent call last):
File "t.py", line 25, in <module>
exec 'action1()' in d
File "<string>", line 1, in <module>
File "<string>", line 10, in action1
NameError: global name 'this_bad_sym_is_not' is not defined
Even if it's not possible to do something similar to this, I'd still like to understand why it's not working.
Thanks!
Maybe this helps: https://wiki.python.org/moin/SandboxedPython
It explains the restricted execution environment.
This is an implementation: https://pypi.python.org/pypi/pysandbox/

Why is double considered a global name?

I've created the code below, when I import the module and attempt to run it I received the following error:
>>> import aiyoo
>>> aiyoo.bixidist(1,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "aiyoo.py", line 50, in bixidist
currentDist = dist(X,Y,c)
File "aiyoo.py", line 39, in dist
distance = math.sqrt(math.pow((X-getLat(i)),2)+math.pow((Y-getLong(i)),2))
File "aiyoo.py", line 28, in getLat
xmlLat = double(xmlLat)
NameError: global name 'double' is not defined
The double function was used in order to convert the unicode output from the XML into a double as input for the functions to follow. So I do not understand why, it is considered to be a name when the aiyoo module is imported.
Here is the module, which was named aiyoo.py:
import math
import urllib2
from xml.dom.minidom import parseString
file = urllib2.urlopen('http://profil.bixi.ca/data/bikeStations.xml')
data = file.read()
file.close()
dom = parseString(data)
#this is how you get the data
def getID(i):
xmlID = dom.getElementsByTagName('id')[i].toxml()
xmlID = xmlID.replace('<id>','').replace('</id>','')
xmlID = int(xmlID)
return xmlID
def getLat(i):
xmlLat = dom.getElementsByTagName('lat')[i].toxml()
xmlLat = xmlLat.replace('<lat>','').replace('</lat>','')
xmlLat = double(xmlLat)
return xmlLat
def getLong(i):
xmlLong = dom.getElementsByTagName('long')[i].toxml()
xmlLong = xmlLong.replace('<long>','').replace('</long>','')
xmlLong = double(xmlLong)
return xmlLong
#this is how we find the distance for a given station
def dist(X,Y,i):
distance = math.sqrt(math.pow((X-getLat(i)),2)+math.pow((Y-getLong(i)),2))
return distance
#this is how we find the closest station
def bixidist(X,Y):
#counter for the lowest
lowDist = 100000
lowIndex = 0
c = 0
end = len(dom.getElementsByTagName('name'))
for c in range(0,end):
currentDist = dist(X,Y,c)
if currentDist < lowDist:
lowIndex = c
lowDist = currentDist
return getID(lowIndex)
As answered by others, double is not a built-in type in python. You have to use, float instead. Floating point is implemented using double in C [ ref ].
And as to the main part of your question i.e. "why the double considered a global name?", when you use a variable-name say double, which is not found in local context, the next lookup is in global context. It is then, if it is not found even in global context, the exception is raised, saying NameError: global name 'double' is not defined.
Happy Coding.
There is no double type in Python. And if you look at the error it complains that it can't find anything named double. The floating-point type in Python is named float.
it should be xmlLat = float(xmlLat)
Python float is same as double of other languages. ( 64 bit )
http://codepad.org/AayFYhEd
Like the other 2 answers so far have said, Python doesn't have a double variable type, instead it has float.
Now for the question in your title and possibly another source of confusion for you. The reason the interpreter is saying "NameError: global name 'double' is not defined" is because of how Python searches for names of functions, variables, objects, etc. This pattern is described by Python's namespace and scope rules. Because you tried to call the nonexistent function Double from within a function without qualifying it (ie. SomeObject.Double(x)), Python first looks for an object of that name in the local namespace (namespace of the current function that is running), then the local namespace of the enclosing functions, then the global namespace, and finally the built-in namespace. The reason the interpreter gave you that message is because of the order of Python's search for the definition of Double(). global namespace was the last place it checked before looking for it in the built-ins (which are Python's coding, not yours, so I guess it wouldn't make sense for the interpreter to say "NameError: built-in name 'double' is not defined"). At least I think this is what's going on. I'm still not a very seasoned programmer, so I trust someone else will correct me if I got something wrong.

Problem grabbing parameters using execfile within a class

I have a problem similar to the first problem in this question, which as far as I can see went unanswered.
I have a file "config.py" which contains a lot of parameters to be used by a class (this config.py file will change), however I can't get these to propagate into the class via execfile.
In an example piece of code:
class Class():
def __init__(self):
execfile("config.py")
print x
# config.py
x = "foo"
>>> t = Class()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __init__
NameError: global name 'x' is not defined
Any help welcome, or any better methods of retrieving parameters from a file to be used in a class.
Many Thanks.
I don't get what you're trying to do (but i don't like it, and this is just me) but to fix your problem do (test in python2.6):
class Class():
def __init__(self):
execfile('config.py', locals()) # Not recommanded, maybe you want globals().
print x
But from the doc:
Note
The default locals act as described
for function locals() below:
modifications to the default locals
dictionary should not be attempted.
Pass an explicit locals dictionary if
you need to see effects of the code on
locals after function execfile()
returns. execfile() cannot be used
reliably to modify a function’s
locals.
and about :
Any help welcome, or any better
methods of retrieving parameters from
a file to be used in a class.
You can use import.
Even though it might be convenient to keep configuration settings in a Python file I would recommend against it. I think it opens up a whole set of problems that you don't really want to have do deal with. Anything could be placed in your configuration file, including malicious code.
I would use either the json module or the ConfigParser module to hold my configuration.
If you have trouble choosing between those two I would recommend the json module. Json is a simple yet flexible format for structured data.

Categories