Getting name of a variable in Python [duplicate] - python

This question already has answers here:
Getting the name of a variable as a string
(32 answers)
Closed 4 months ago.
If I have local/global variable var of any type how do I get its name, i.e. string "var"? I.e. for some imaginary function or operator nameof() next code should work:
var = 123
assert nameof(var) == "var"
There's .__name__ property for getting name of a function or a type object that variable holds value of, but is there anything like this for getting name of a variable itself?
Can this be achieved without wrapping a variable into some magic object, as some libraries do in order to get variable's name? If not possible to achieve without magic wrappers then what is the most common/popular wrapping library used for this case?

You can do this with the package python-varname: https://github.com/pwwang/python-varname
First run pip install varname. Then see the code below:
from varname import nameof
var = 123
name = nameof(var)
#name will be 'var'

For Python 3.8 and later, you can try this not-so-pretty way, but it works for any python object that has a str-method:
var = 123
var_name = f'{var=}'.partition('=')[0]

def get_veriable_name(variable):
current_file = os.path.basename(__file__)
with open(current_file, "r") as f:
for line in f:
if variable in line:
return line.split("=")[0].strip()
return None

Related

Python: why aren't imported variables updating? [duplicate]

This question already has answers here:
How to change a module variable from another module?
(3 answers)
Closed 5 years ago.
This is apparently the same question as this (S.O. didn't find it until later). Am investigating duping. However, the title line alone makes this a useful question.
In the following (two) chunks of code, why don't I get the updated value when I import?
Two files: import.py and export.py
Here is export.py:
i=12345
def change_i(x):
global i
i=x
print "export changed i to {0}".format(repr(i))
Here is import.py:
from export import i, change_i
print "Import gets i={0}".format(repr(i))
change_i(5)
print "Import has i={0}".format(repr(i))
Here is the result:
> python import.py
Import gets i=12345
export changed i to 5
Import has i=12345
Why isn't import.py getting the new value 5????
NOPE. TURNS OUT THIS IS A LIE/MISCONCEPTION.
When you import, you import the current value of the imported symbol and add it to your namespace as defined. You are not importing a reference, you are importing a value.
Thus, to get the updated value of i, you must import a variable that holds a reference to that symbol.
In other words, importing is NOT like an import in JAVA, external declaration in C/C++ or even a use clause in PERL.
Rather, the following statement in Python:
from some_other_module import a as x
is more like the following code in K&R C:
extern int a; /* import from the EXTERN file */
int x = a;
(caveat: in the Python case, "a" and "x" are essentially a reference to the actual value: you're not copying the INT, you're copying the reference address)
This is sneakily defined in the Python language reference: the use of object instead of symbol. I would suggest that the Python language reference make this more clear and less legal.
The from form does not bind the module name: it goes through the
list of identifiers, looks each one of them up in the module found in
step (1), and binds the name in the local namespace to the object thus
found.

How to get user defined variable in Python? [duplicate]

This question already has answers here:
List user defined variables, python
(5 answers)
Closed 6 years ago.
This have been searched on Google and on Stack-Overflow, before asking the question, without success. Hence, this is not a trivial question...
I have two modules : Main and module1 and am doing this code in Main :
import module1
dict1= module1.getdict_userdefinedvariable()
dict1 is then manipulated in a programmatic way to check (assertion, validation,..).
However, if in getdict_userdefinedVariable(), I am using Globals() or Vars(),
I have access ONLY to the variables defined in the sub-module.
Also, Globals(), Vars() or Ipython who_ls gives the list of all names including user-defined module names, user-defined function names.
So,How can we get variables defined in Main module and filter only user-defined variables by removing USER defined module, USER defined function names ?
There is
who_ls in ipython,
but it contains module and function names....
Does not this really work for You? I tried - got my vars listed:
All credits to Niek de Klein, this is his answer from:
List user defined variables, python
If you don't put any underscores in front of your variables you could do:
#!/us/bin/python
foo1 = "Hello world"
foo2 = "bar"
foo3 = {"1":"a", "2":"b"}
foo4 = "1+1"
for name in dir():
if not name.startswith('__'):
myvalue = eval(name)
print name, "is", type(myvalue), "and is equal to ", myvalue

Python: Dynamic "from" import [duplicate]

This question already has answers here:
How can I import a module dynamically given its name as string?
(10 answers)
How can I import a module dynamically given the full path?
(35 answers)
Closed 3 months ago.
So i'm trying to turn a bunch of "from x import x" statements, that look like this:
from class_foo import class_foo
into something dynamic. I'm trying to pass a path to a directory and have it import all of the modules therein.
def dynamicImport(dirPath):
filez = os.listdir(dirPath)
for file in filez:
if "class" in file:
oname = file[:-3] #cut off the file extension, trivial
imp_statement = "from " + oname + " import " + oname
#when I print imp_statement, I can verify it's being concatenated correctly
exec(imp_statement)
When I run this function and pass it a path, the statement strings are being created properly and it produces no errors, yet then later I'll try to access one of the imported objects, and this happens:
foo = class_foo()
NameError: name 'class_foo' is not defined
Clearly I'm doing something wrong. Any help would be appreciated.
You're execing your import statement in your function's local namespace, so that's where the names are defined. This namespace goes away when the function ends, leaving you with nothing. What you probably want is something like exec imp_statement in globals().
Why not just use __import__() instead of string-munging? Then you get a reference to your module. You can then fish out the class reference using getattr() on the module object and insert that into globals() (or just pass a dictionary back to the caller, who can then do globals().update() with it).
import sys, os
def getClasses(directory):
classes = {}
oldcwd = os.getcwd()
os.chdir(directory) # change working directory so we know import will work
for filename in os.listdir(directory):
if filename.endswith(".py"):
modname = filename[:-3]
classes[modname] = getattr(__import__(modname), modname)
os.setcwd(oldcwd)
return classes
globals().update(getClasses(r"C:\plugin_classes"))
Something like that. Or rather than updating globals() with your modules, which could clobber a global variable you care about, just leave the classes in the dictionary and reference them from there:
classes = getClasess(r"C:\plugin_classes")
for clas in classes.itervalues():
instance = clas(1, 2, 3) # instantiate
instance.dosomething_cool(42) # call method
Python >= 2.7 has importlib (you can pip install importlib to use importlib in earlier versions of python)
module = importlib.import_module("path.to.module")
MyClass = module.MyClass
Suppose your directory structure looks like this:
./ <- you are here
- main.py
- my_package/
- __init__.py
- my_module.py
and you want to dynamically import my_module.py, to use some of its functions, classes, whatever. Then, using importlib, you can use the following code in main.py:
import importlib
pack = "my_package"
mod = "my_module"
module = importlib.import_module("." + mod, pack)
# or, alternatively
module = importlib.import_module(".".join(pack, mod))
module.func("hello") # if my_package/my_module.py defines function "func"
obj = module.MyClass("world") # if my_package/my_module.py defines class "MyClass"
It's been a long time since I've worked with Python. But I think your problem might lay in the fact that "oname" is a string. The line from class_foo import class_foo is not a string. One painstaking option would be to have your code make a whole new .py file that would have all of the imports. So you would write all of your current file plus the new imports to, basically, a text file ending in .py
Take a look at the __import__ function

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.

How to determine if a variable exists in another Python file

I have two python files. From python file #1, I want to check to see if there is a certain global variable defined in python file #2.
What is the best way to do this?
You can directly test whether the file2 module (which is a module object) has an attribute with the right name:
import file2
if hasattr(file2, 'varName'):
# varName is defined in file2…
This may be more direct and legible than the try… except… approach (depending on how you want to use it).
try:
from file import varName
except ImportError:
print 'var not found'
Alternatively you could do this (if you already imported the file):
import file
# ...
try:
v = file.varName
except AttributeError:
print 'var not found'
This will work only if the var is global. If you are after scoped variables, you'll need to use introspection.
With the getattr() built-in function you also can specify a default value like:
import file2
myVar = getattr(file2, attribute, False)
See the documentation

Categories