I have a number of constants,variable in which i keep names.
ATTR_ITEM_NAME = 'pro'
I check if the attribute is attached to an objects:
if hasattr(obj1, ATTR_ITEM_NAME):
then if exist I want the attribute value to be passed to an attribute of an object, something like this:
obj2.fm = obj1.ATTR_ITEM_NAME
ATTR_ITEM_NAME being a string and not an attribute is an error, I need something that works;
Python also has getattr which works like hasattr but returns the value:
obj2.fm = getattr(obj1, ATTR_ITEM_NAME)
If you are not sure the attribute exists you could:
assign a default value (e.g. None)
DEFAULT = None
obj2.fm = getattr(obj1, ATTR_ITEM_NAME, DEFAULT)
or catch the exception using
try:
obj2.fm = getattr(obj1, ATTR_ITEM_NAME)
except AttributeError:
pass # or do something else...
Related
I need to check for empty values of every field of a distinct object. And I'm tiered of typing it out.
In this case. I have the an object called signal with multiple fields, which should not be empty.
if self.is_blank(signal.provider_id):
error_response = "Signal rejected. No signal provider id given."
elif self.is_blank(signal.sequence_id):
error_response = "Signal rejected. No signal sequence id provided."
....
def is_blank (self, string):
"""Checks for None and empty values"""
return True if string and string.strip() else False
Anyhow, what is the fast way in python to check all fields for "emptiness"? How do we loop them?
You may want to use operator.attrgetter:
def is_blank(self, field_names):
for name in field_names:
if getattr(self, name) and getattr(self, name).strip():
return True, name
return False, None
...
is_blank, name = self.is_blank(['provider_id', 'sequence_id', ...])
if is_blank:
print(f'Signal rejected. No signal {name} provided.')
You can also implement is_blank with next:
def is_blank(self, field_names):
return next(
((True, name)
for name in field_names
if getattr(self, name) and getattr(self, name).strip()),
(False, None),
)
This is going to print an error message for the first field that is failing the check. All you need to do is to provide a complete list of the attributes to be checked.
As rostamn mentioned, you can convert your object into a dictionary,
after which you can loop through the (key, values) in a single line with a filter and check the result like so:
any_empty = any([True for x, y in your_obj.__dict__.items() if not y])
Change the condition in the loop to the type of empty check you need.
To loop over all instance properties you use my_instance.__dict__
see this answer for details: Explain __dict__ attribute
I have a simple for loop which iterates through all objects in a local database. For each object, I reference a presalesEngineer and pass that ID to an API call to retrieve a JSON response. However, there are records in the database for which there is no value for presalesEngineer. When this is the case, the empty string throws a HttpError when a bad URL is passed to the API call. How can I handle when presalesEngineer does not exist, so the API is not passed an empty value?
views.py
objects = Opportunity.objects.all()
for object in objects:
try:
ps_e = object.presalesEngineer
if ps_e:
presales_engineers = [cwObj.get_member_by_id(ps_e) for object in objects]
else:
presales_engineers = 'None'
except NameError:
presales_engineers = 'None'
This codeblock should try to grab the presalesEngineer of your object or return None (note that the string 'None' does not equal the pytohon object None)
for object in objects:
try:
ps_e = object.presalesEngineer
# Do stuff with an object you know for sure will not trigger an exception
# Something like:
# if ps_e != '': < the object is not an empty string
# or
# if ps_e: < the object is not None
# after you pass whatever checks you deem necessary, you launch your API call.
except AttributeError:
# You can either pass here or return a None object/Empty list
ps_e = None
Possible implementation below:
# Empty list of whatever you are searching for
engineers = []
for my_object in objects:
try:
ps_e = my_object.presalesEngineer
# This is here to avoid none values in your API call
if ps_e:
# Just in case your API call falls
# It will fail silently in this try codeblock
try:
# Assuming cwObj is your driver/API endpoint builder
# And that you only get one single string as response
# And that string is not some data structure that you need to split
my_desired_id = cwObj.get_member_by_id(ps_e)
engineers.append(my_desired_id)
# Using bare except statements is not a good idea
# Use HttpError here if you don't want to pass on any exception
except:
pass
except AttributeError:
# You can either pass here or return a None object/Empty list
pass
print engineers
I am trying to write a function that will print the values of a object but only those values that are defined in a list.
import boto.ec2.cloudwatch
conn = boto.ec2.cloudwatch.connect_to_region('ap-southeast-1')
alarms = conn.describe_alarms()
for alarm in alarms:
print alarm.name
this will return a particular value for all alarms. How ever I want to make it work in such a way that I am able to print all the values that are defined in a list. Here is what I am trying to do
import boto.ec2.cloudwatch
conn = boto.ec2.cloudwatch.connect_to_region('ap-southeast-1')
alarms = conn.describe_alarms()
whitelist = ["name", "metric", "namespace"]
for alarm in alarms:
print alarm.whitelist[0]
However this wont works of course. Any suggestion about what will be the best way to do that? SO that I am able to print everything that is defined in a whitelist.
You can use getattr (note that you are referring to attributes, or possibly methods, not functions):
for alarm in alarms:
for attr in whitelist:
print getattr(alarm, attr)
getattr takes an optional third argument, the default value in case attr isn't found, so you could do e.g.:
for attr in whitelist:
print "{0}: {1}".format(attr, getattr(alarm, attr, "<Not defined>"))
You can use the getattr() built-in function.
Your code would looks something like this:
import boto.ec2.cloudwatch
conn = boto.ec2.cloudwatch.connect_to_region('ap-southeast-1')
alarms = conn.describe_alarms()
whitelist = ["name", "metric", "namespace"]
for alarm in alarms:
for attribute in whitelist:
print(getattr(alarm, attribute))
I'm making my first attempts at Python.
I need to loop over a log, parse log entries and then update an object, which includes nested objects for machines listed in the log.
This is what I have:
import re
format_pat= re.compile(
r"(?P<host>(?:[\d\.]|[\da-fA-F:])+)\s"
r"(?P<identity>\S*)\s"
r"(?P<user>\S*)\s"
r"\[(?P<time>.*?)\]\s"
r'"(?P<request>.*?)"\s'
r"(?P<status>\d+)\s"
r"(?P<bytes>\S*)\s"
r'"(?P<referer>.*?)"\s'
r'"(?P<user_agent>.*?)"\s*'
)
from json import JSONEncoder
class MyEncoder(JSONEncoder):
def default(self, o):
return o.__dict__
# JSON response object
class ResponseObject(object):
def __init__(self, dict):
self.__dict__ = dict
# check for JSON response object
try:
obj
except NameError:
obj = ResponseObject({})
test = ['2001:470:1f14:169:15f3:824f:8a61:7b59 - SOFTINST [14/Nov/2012:09:32:31 +0100] "POST /setComputer HTTP/1.1" 200 4 "-" "-" 102356']
# log loop
for line in test:
try:
# try to create object from log entry
m = format_pat.match(line)
if m:
res = m.groupdict()
res["status"] = int(res["status"])
# register machine if not done
if not hasattr(obj, res["user"]):
setattr(obj, res["user"], {"downtime":"0","flag":"false","downstart":"0","init":res["time"],"last":"","uptime":"","downtime":"","totaltime":""})
machine = getattr(obj, res["user"])
flag = machine["flag"]
start = machine["downstart"]
down = machine["downtime"]
last = machine["last"]
print "done"
# set last
last = res["time"]
# PROBLEM this does not work
setattr(machine, last, res["time"])
print machine
else:
print "nope"
except:
print "nope base"
print MyEncoder().encode(obj)
The error I'm getting when trying to setattr() is
AttributeError: 'dict' object has no attribute ''
but I was afraid it was not as easy as this...
Question:
How do I update the last value in my nested object using 'setattr'? Or is there another way to update nested object attributes?
I think you need to do this:
setattr(machine, 'last', res["time"])
As setattr needs a string of the name of the attribute to be set
Do not use setattr. Just assign a value to the "last" key for each machine dictionary.
(actually you answered your own question!)
I don't understand why, but I can set the value of last like this:
print machine
print machine["last"]
print res["time"]
# this works
machine["last"] = res["time"]
print machine
If someone can explain, would be nice :-)
I have an ORM mapped object, that I want to update. I have all attributes validated and secured in a dictionary (keyword arguments). Now I would like to update all object attributes as in the dictionary.
for k,v in kw.items():
setattr(myobject, k, v)
doesnt work (AttributeError Exception), thrown from SQLAlchemy.
myobject.attr1 = kw['attr1']
myobject.attr2 = kw['attr2']
myobject.attr3 = kw['attr3']
etc is horrible copy paste code, I want to avoid that.#
How can i achieve this? SQLAlchemy already does something similar to what I want to do in their constructors ( myobject = MyClass(**kw) ), but I cant find that in all the meta programming obfuscated crap in there.
error from SA:
<< if self.trackparent:
if value is not None:
self.sethasparent(instance_state(value), True)
if previous is not value and previous is not None:
self.sethasparent(instance_state(previous), False)
>> self.sethasparent(instance_state(value), True)
AttributeError: 'unicode' object has no attribute '_sa_instance_state'
myobject.__dict__.update(**kw)
You are trying to assign a unicode string to a relation attribute. Say you have:
class ClassA(Base):
...
b_id = Column(None, ForeignKey('b.id'))
b = relation(ClassB)
And you are trying to do:
my_object = ClassA()
my_object.b = "foo"
When you should be doing either:
my_object.b_id = "foo"
# or
my_object.b = session.query(ClassB).get("foo")