Retrieve details from AttributeError object in Python - python

I am enumerating some objects in a list, which may or may not have certain properties. If a property does not exists, I get the AttributeError. What I want to do is to catch the exception object and retrieve the specific property that causes the error and set it to an empty string. I don't see any method in the AttributeError object to retrieve the said attribute.
Partial code here:
import wmi
c = wmi.WMI ()
for account in c.Win32_Account():
try:
print(f"Name: {account.Name}, FullName: {account.FullName}, LocalAccount: {account.LocalAccount}, Domain: {account.Domain}")
except AttributeError as error:
# How do I retreive the attribute in question from the exception object?

Per original post, you want to "retrieve the specific property that causes the error and set it to an empty string".
if you just wanted to print the string use getattr:
https://docs.python.org/3/library/functions.html#getattr
import wmi
c = wmi.WMI ()
for account in c.Win32_Account():
print(f"Name: {getattr(account, 'Name', "")}, FullName: {getattr(account, 'FullName', "")}, LocalAccount: {getattr(account, 'LocalAccount', "")}, Domain: {getattr(account, 'Domain', "")}")
if you want to actually overwrite the missing values use hasattr and setattr:
for account in c.Win32_Account():
for attr in ['Name', 'FullName', 'LocalAccount', 'Domain']:
if not hasattr(account, attr):
setattr(account, attr, "")

Every Exception object stores its arguments in the .args property. The argument to an AttributeError object is a string that contains the object on which the property access is being used and the property being accessed.
The format of this message looks like-
('|")object_name('|") object has no attribute ('|")property_name('|")
Where ('|") means "either matching double quotes or single quotes"
You can extract both the object name and property name using this regex-
(?:\'|")(\w+)(?:\'|")
So the final implementation would look like-
import wmi
import re
c = wmi.WMI ()
for account in c.Win32_Account():
try:
print(f"Name: {account.Name}, FullName: {account.FullName}, LocalAccount: {account.LocalAccount}, Domain: {account.Domain}")
except AttributeError as error:
property_name = re.findall(r'(?:\'|")(\w+)(?:\'|")', error.args[0])[-1]

Related

Get class and attribute names from AttributeError

How do I get the class and missing attribute from AttributeError, e.g.
when AttributeError says: 'NoneType' object has not attribute a, I would like to get "NoneType" and "a".
Looks like the only thing you can retrieve from an AttributeError is the string with the error message:
try:
str.s
except AttributeError as err:
error_message, = err.args
print("Error message:", error_message)
raise
For getting the type information out of an AttributeError, you could probably use regex, since you know the format of the error message:
import re
try:
None.attr
except AttributeError as e:
matches = re.match(r"'([^']*)' object has no attribute '([^']*)'", str(e))
obj_type = matches.group(1)
attr_name = matches.group(2)
print(f"Object type: {obj_type}, attribute name: {attr_name}")
# Object type: NoneType, attribute name: attr
import re
try:
# access attribute
except AttributeError as e:
obj_type, attr_name = re.match(r"\'([a-zA-Z0-9\_]+)\' object has no attribute \'([a-zA-Z0-9\_]+)\'", str(e)).groups()
First cast the error into text with str(e)
Then, using regular expression pattern read the object type and the name of the attribute you're trying to access. The groups() method will return all the captured groups from the regex which are marked with parenthesis.

AttributeError: 'contactObject' object has no attribute

This is my function:
def get_content(self):
full_results = []
for res in self._get_data(): #function that returns suds object
final_dict = dict(res)
final_dict.pop('readOnlyContactData', None)
if res["readOnlyContactData"] is not None:
readOnlyContactData_dict = dict(res["readOnlyContactData"])
final_dict.update(readOnlyContactData_dict)
full_results.append(final_dict)
return full_results
However when runnning it I get:
INFO - if res["readOnlyContactData"] is not None:
INFO - File "/home/ubuntu/.local/lib/python3.6/site-packages/suds/sudsobject.py", line 154, in __getitem__
INFO - return getattr(self, name)
INFO - AttributeError: 'contactObject' object has no attribute 'readOnlyContactData'
INFO - Command exited with return code 1
I don't understand why it fails the if condition is suppose to check if res["readOnlyContactData"] exists. if it does process it and if not ignore it.
Why this condition fails?
In python, using variable['key'] syntax internally calls __getitem__('key') to retrieve the right element. In your case, the error indicates that __getitem__() internally calls getattr(), which is usually used to retrieve a class member or an instance variable.
File "/path/to/sudsobject.py", line 154, in __getitem__
return getattr(self, name)
AttributeError: 'contactObject' object has no attribute 'readOnlyContactData'
So, based on information you provided, calling res["readOnlyContactData"] seems equivalent to call res.readOnlyContactData. Since readOnlyContactData attribute is not found in your object (of type contactObject), you get this error.
Try the following statements to check wether your object has the member you are looking for or not:
>>> # this has to be implemented in your class
>>> "readOnlyContactData" in res
or
>>> hasattr(res, "readOnlyContactData")
That if condition checks whether the element residing in res["readOnlyContactData"] is None or not. So, if res does not have any index named "readOnlyContactData" Python returns the exception Object has no attribute. Instead of the if-statement you should try hasattr(res, "readOnlyContactData")

How to pass variable name instead of method name in python

I'm using Google Places API code to get the places and its details so in that code I want to pass variable name instead of its attribute type
Here is the snippet
WORKS FINE
query_result = google_places.nearby_search(
location='London, England', keyword='Fish and Chips',
radius=20000, types=[types.TYPE_FOOD])
GIVES ERROR
place_type='TYPE_FOOD'
query_result = google_places.nearby_search(
location='London, England', keyword='Fish and Chips',
radius=20000, types=[types.place_type])
AttributeError: module 'googleplaces.types' has no attribute 'place_type'
Any suggestion on how can it be done?
Thanks
Domnick
You can use getattr
1) If TYPE_FOOD is a property you can use:
getattr(types, place_type)
2) If TYPE_FOOD is a method, you should call it:
getattr(types, place_type)()
Note: I am assuming that your method takes no arguments.

How can I see instance attributes of the object returned by app.request in web.py?

from bin.app import app
resp = app.request('/')
print resp.__dict__.keys()
print vars(resp)
print resp.__class__.__dict__.keys()
I know app.request returns an object with the data attributes 'headers', 'status' and 'data'. All I want to do is print them out, but none of the print statements above show that these exist.
Is there some way of finding these attributes (without using the help docs)?
The storage object resp has a __getattr__ method--which I found using dir(resp)--that you can use to list the attributes.

AppEngine -> "AttributeError: 'unicode' object has no attribute 'has_key'" when using blobstore

There have been a number of other questions on AttributeErrors here, but I've read through them and am still not sure what's causing the type mismatch in my specific case.
Thanks in advance for any thoughts on this.
My model:
class Object(db.Model):
notes = db.StringProperty(multiline=False)
other_item = db.ReferenceProperty(Other)
time = db.DateTimeProperty(auto_now_add=True)
new_files = blobstore.BlobReferenceProperty(required=True)
email = db.EmailProperty()
is_purple = db.BooleanProperty()
My BlobstoreUploadHandler:
class FormUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
try:
note = self.request.get('notes')
email_addr = self.request.get('email')
o = self.request.get('other')
upload_file = self.get_uploads()[0]
# Save the object record
new_object = Object(notes=note,
other=o,
email=email_addr,
is_purple=False,
new_files=upload_file.key())
db.put(new_object)
# Redirect to let user know everything's peachy.
self.redirect('/upload_success.html')
except:
self.redirect('/upload_failure.html')
And every time I submit the form that uploads the file, it throws the following exception:
ERROR 2010-10-30 21:31:01,045 __init__.py:391] 'unicode' object has no attribute 'has_key'
Traceback (most recent call last):
File "/home/user/Public/dir/google_appengine/google/appengine/ext/webapp/__init__.py", line 513, in __call__
handler.post(*groups)
File "/home/user/Public/dir/myapp/myapp.py", line 187, in post
new_files=upload_file.key())
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 813, in __init__
prop.__set__(self, value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3216, in __set__
value = self.validate(value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3246, in validate
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
What perplexes me most is that this code is nearly straight out of the documentation, and jives with other examples of blob upload handler's I've found online in tutorials as well.
I've run --clear-datastore to ensure that any changes I've made to the DB schema aren't causing problems, and have tried casting upload_file as all sorts of things to see if it would appease Python - any ideas on what I've screwed up?
Edit: I've found a workaround, but it's suboptimal.
Altering the UploadHandler to this instead resolves the issue:
...
# Save the object record
new_object = Object()
new_object.notes = note
new_object.other = o
new_object.email = email.addr
new_object.is_purple = False
new_object.new_files = upload_file.key()
db.put(new_object)
...
I made this switch after noticing that commenting out the files line threw the same issues for the other line, and so on. This isn't an optimal solution, though, as I can't enforce validation this way (in the model, if I set anything as required, I can't declare an empty entity like above without throwing an exception).
Any thoughts on why I can't declare the entity and populate it at the same time?
You're passing in o as the value of other_item (in your sample code, you call it other, but I presume that's a typo). o is a string fetched from the request, though, and the model definition specifies that it's a ReferenceProperty, so it should either be an instance of the Other class, or a db.Key object.
If o is supposed to be a stringified key, pass in db.Key(o) instead, to deserialize it.
Object is a really terrible name for a datastore class (or any class, really), by the way - the Python base object is called object, and that's only one capitalized letter away - very easy to mistake.
has_key error is due to the ReferenceProperty other_items. You are most likely passing in '' for other_items when appengine's api expects a dict. In order to get around this, you need to convert other_items to hash.
[caveat lector: I know zilch about "google_app_engine"]
The message indicates that it is expecting a dict (the only known object that has a has_key attribute) or a work-alike object, not the unicode object that you supplied. Perhaps you should be passing upload_file, not upload_file.key() ...

Categories