I have a dataframe listing individual names, and for each one I have an identically-named object storing attributes about them. However, when iterating through the dataframe, I don't know how to use the listed name to access the correct object (which I want to pull an attribute from).
person = df._get_value(n, 'People')
getattr(person, 'Age')
When I run this, I get an Attribute Error because its attempting to access 'Age' in the string, but not the matching object. How should I convert the string dynamically so I can access the correct object?
You can use inbuilt function import (mind the double underscore). Sample code below
module = __import__("name of the package", globals(), locals(), ["moduleName"], 0)
obj_class = getattr(module, "moduleName")
cclass = obj_class()
getattr(cclass, "attributeName")
You can view this doc for more details on importlib
Related
Currently I am working on a selenium project which I am integrated with Jenkins.I have stored Locators in a class. So my target is to take input from jenkins and use that variable as a key to get value from the
class Locators(object):
rundate = 'PREV' # This value is user input, either PREV or NOW
PREV = 'abcd'
NOW = 'bcd'
So I want to use it as:
Test = Locators()
Test.(Test.rundate)
Dotted attribute access always requires a valid identifier for the attribute name, not an arbitrary expression. Use getattr in other situations.
getattr(Test, Test.rundate)
I am trying to parse a json MSG into a python dict.
For reference, the message is received from the Things Network with the python MQTT handler.
Here is the format I am receiving when I print the object
msg = MSG(variable_group=MSG(data0=0, data1=0, data2=0), variable2='name', variable3='num')
In its default state, I can access individual fields by msg.variable2 for example which provides 'name' but does not provide the variable name itself.
This is fine for a scenario in which I hardcode everything into my system, but I would like it to be a bit more adaptable and create new entries for variables as they come in.
Is there any way to parse this in such a way that I get both the data and the variable name?
Thanks!
EDIT:
From the input above, I would like to get a python dict containing the variable name and data.
dict =
{
variable_group : MSG(data0=0, data1=0, data2=0),
variable2 : 'name',
variable3 : 'num'
}
Currently, I can access the data via a for loop and can print the variable names if I print the entire structure, but cannot access the variable names through a looping mechanism
EDIT 2:
After doing some digging on the wrapper found the following:
def _json_object_hook(d):
return namedtuple("MSG", d.keys())(*d.values())
def json2obj(data):
return json.loads(data, object_hook=_json_object_hook)
Where the input shown above is created by passing it as 'data' to json2obj.
I am still unsure how to get a dict out of this format, haven't used object_hooks before.
From discussion in the comments below, it appears that the MSG object is a namedtuple created on the fly out of the json object.
In a case like that you can get the fields by looking at the _fields of the object. You can dict-ify a namedtuple like this
def nt_to_dict(nt):
return {field, getattr(nt, field) for field in nt._fields}
or you could just inspect the object by trolling _fields in code and using getattr as needed
I struggle with using variables (ultimately dictionary) for dynamically compose and access class attributes using getattr:
from gpiozero import PiStop
lights = PiStop('A+')
# working call: lights.red.on()
var = 'red.on'
getattr(lights(), var) # doesn't work - error
I cannot find proper syntax...
You have two attributes being accessed; lights.red is one such attribute, and on the result of that access, you then apply another attribute access, so <result>.on.
You need to use separate getattr() calls to achieve the same.
You could split on the '.' dot in var and apply each name separately, in a loop:
result = lights()
for name in var.split('.'):
result = getattr(result, name)
This allows for var to be set to any number of nested attributes.
I have a Python class , having some variables. The definition of the class is as follows:
class student:
def __init__(self,name,rollno,DOB,branch):
self.name=name
self.rollno=rollno
self.DOB=DOB
self.branch=branch
self.books=[]
self.fines=[]
I am adding new attributes for a student , and need to store the corresponding values as well (for future use). This is done using the setattr method, and works fine.
Code snippet:
setattr(student,"date_of_join",date())
Now I am approaching the problem as, if the user adds a new attribute (say, "date_of_join"), then I update a list (studattr), initially containing ["name","rollno",DOB","branch","books","fines"] to update the list of attributes. This means that the updated list will also have "date_of_join" now appended to it.
Now if I want to access this list of attributes of a student Instance, then how do I do it? ( Since the records are dynamically updated, and let us suppose I have to access x.date_of_join, then how do I join the two strings? Is there anything similar to python's os.path.join, or rather linux's system call, (merging two strings)? )
Problem:
for attribute in studattr:
print attribute,x.attribute
{ This throws an Exception since the instance x has no variable or method named "attribute")
PS: I tried using inspect,inspect.getmembers(x) as well as dirs(x), vars(x) ,(mentioned on stackoverflow), but it only gives me a list of variables/methods in main class body and not in init.
Use getattr() to access dynamic attributes:
for attr in student.studattr:
print attr, getattr(student, attr)
or use vars() will give you a dictionary of current attributes on a student:
for attr, value in vars(student).iteritems():
print attr, value
I would like to ask what does it mean "AttributeError: 'unicode' object has no attribute 'has_key'"
Here is the full stack trace:
Traceback (most recent call last):
File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\webapp\__init__.py", line 509, in __call__
handler.post(*groups)
File "D:\Projects\workspace\foo\src\homepage.py", line 71, in post
country=postedcountry
File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 656, in __init__
prop.__set__(self, value)
File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 2712, in __set__
value = self.validate(value)
File "D:\Projects\GoogleAppEngine\google_appengine\google\appengine\ext\db\__init__.py", line 2742, in validate
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
Let me describe a little bit more about the situation:
First I created the models.py that has the db.Model for CMSRequest which has an attribute country that reference to the CMSCountry class
class CMSRequest(db.Model):
country = db.ReferenceProperty(CMSCountry, required=True)
class CMSCountry(db.Model):
name = db.StringProperty(required=True)
Then, I created a bulkloader class to import the data into the CMSCountry
In the form, user can select the country from the drop down list box, the results are posted back and save to the CMSRequest object
def post(self):
postedcountry = self.request.get('country')
cmsRequest = models.CMSRequest(postedcountry)
Maybe I have found the solution to my question, it is because I have not converted the posted key of CMSCountry back to save to the CMSRequest.
Thank you everyone!
In this line:
if value is not None and not value.has_key():
value is a unicode string. It looks like the code is expecting it to be a db.Model,
(From what I can see, has_key is a method of db.Model, as well as a method of Python dictionaries, but this must be the db.Model one because it's being called with no arguments.)
Are you passing a string to a GAE API that expects a db.Model?
Your problem is that postedcountry is a string and not a country object. Values retrieved from self.request.get are the string values of variables passed by the browser.
You need to look up a country object using some GQL. Exactly how you do that will depend on what exactly the country field of your HTML form is returning , Object Key?, country name?
def post(self):
postedcountry = self.request.get('country')
# <-------- Need to look up a country here !!!!!
cmsRequest = models.CMSRequest(country=postedcountry)
Note: normally "mapping" types in Python (dictionaries and dictionary like classes ... such as various types of dbm (indexed file) and some DBMS/ORM interfaces ... will implement a has_key() method.
Somehow you have gotten a Unicode (string) object into this statement when you were expecting to have some sort of dictionary or other mapping object reference.
In general AttributeError means that you have tangled up your object bindings (variable assignments). You've given a name to some object other than the type that you intended. (Or sometimes it means you have a typo like ".haskey()" instead of has_key() ... etc).
BTW: the use of has_key() is somewhat dated. Normally it's better to test your containers with the Python in operator (which implicitly calls __contains__() --- and which works on lists, strings, and other sequences as well as mapping types).
Also value.has_key() would raise an error even if value were a dictionary since the .has_key() method requires an argument.
In your code I would either explicitly test for if postedcountry is not None: ... or I'd supply your .get() with an (optional) default for "postedcountry."
How do you want to handle the situation where request had no postedcountry? Do you want to assume it's being posted from some particular default? Force a redirection to some page that requires the user to supply a value for that form element? Alert the Spanish Inquisition?
If you read the traceback, it'll tell you exactly what is going on:
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
What this says is the the value variable which you're using doesn't have the has_key attribute. And, what it's telling you is that your value variable isn't a dictionary, as it looks like you're expecting...instead, it's a unicode object, which is basically a string.
You're attempting to set a string to a ReferenceProperty. The 'country' field of CMSCountry is a db.ReferenceProperty, which takes a db.Key or a CMSCountry object, but you're attempting to set it to a string.
You should be doing something like this:
def post(self):
postedcountry = self.request.get('country')
country = models.CMSCountry.all().filter('name =', postedcountry)
if not country:
# Couldn't find the country
else:
cmsRequest = models.CMSRequest(country=country)
Please do file a bug about the rather unhelpful error message, though.
The dictionary object's has_key() method is deprecated in 3.0 - use the "in" expression instead. If you are using the old library in 3.x, you must make code changes to accommodate it.