I apology ahead if this is a repost.
I'm currently using a following "self-invented" verification method to check if a Class's attribute (or method) exists before trying to access it:
if 'methodName' in dir(myClassInstance): result=myClassInstance.methodName()
I wonder if there is a more common "standardized" way of doing the same.
Use hasattr. It returns True if a given object has a given name as an attribute, else False:
if hasattr(myClassInstance, 'methodName'):
... # Whatever you want to do as a result.
Use hasattr(myClassInstance, 'methodName').
Another possibility is to just try accessing it and handle the exception if it's not there:
try:
myClassInstance.methodName()
except AttributeError:
# do what you need to do if the method isn't there
How you'll want to handle this depends on why you're doing the check, how common it is for the object to not have that attribute, and what you want to do if it's not there.
Related
I have an API in Python which can return an object, or None if no object is found. I want to avoid run-time exceptions/crashes, etc., hence I want to force the users of my API, to do an is not None test.
For example:
x = getObject(...)
if x is not None:
print x.getName() #should be o.k.
y = getObject(...)
print y.getName() # print an error to the log
How can I achieve that?
In comparable code in C++, I can add a flag that will be checked when I call the getName(); the flag is set only upon comparing the object to NULL.
In Python, however, I am unable to overload the is operator. Are there any other ways I can achieve that functionality in Python?
You cannot force the use of if x is not None because you cannot override the behavior of id(). The is operator internally compares the ids of the two objects being compared, and you have no way of controlling that behavior.
However, you can force the use of if x != None or if not x == Noneby overriding the __eq__ and __ne__ methods of your class, respectively.
This is not good practice, however. As #Kevin has noted in the comments, is is the preferred operator to use when comparing to None.
What I would do is write clear and organized documentation for this API, and then clearly warn users that the instantiation could fail and return None. Then, gently nudge users towards good practices by providing an example with the built-in getattr function or an example with the is not None check.
Like it was already said, you can't override is behavior.
To do what you want, basically you can create a surrogate object that has a getName() function. To let the user check if the function failed, you can have the object evaluate to False. (This is a standard practice and I think this is better than making the object equal to None with the __eq__ operator). To do this, you can override override __nonzero__() having it return False.
Example:
class GetObjectFailed(object):
def __nonzero__():
return False
def getName():
return "An error has occurred" # You could specify a specific error message here...
x = getObject(...)
print x # prints "An error has occurred"
if x:
# This is the recommended way of doing things
# Do something with the object
x.proccess()
if x is not None:
# This will never work
x.proccess()
if x != None:
# This is possible but not recommended
x.proccess()
I Know what the error:
AttributeError: 'NoneType' object has no attribute 'something'
means, but what I cannot figure out is how to catch it. Basically i want to check to see if my object is created or not.
I want to do something like this:
try:
test = self.myObject.values()
except:
print "Error happened"
But every time I do I get:
AttributeError: 'NoneType' object has no attribute 'values'
Can someone tell me how to catch this?
you can use the hasattr(object, name) method which returns True or False. If you try to access an attribute which does not exist you will always receive an exception. https://docs.python.org/2/library/functions.html#hasattr
If you still wish to catch the exception then simply do a try/catch block with exception type 'AttributeError'
There are a number of ways to do this. If you just want to see if an object exists, you can do:
if self.myObject:
# do stuff with my object
else:
# do other stuff
#Or the more explicit form, if myObject could be 'falsey' normally, like an empty list/dict
if self.myObject is not None:
If you can assign a reasonable default, you can one-line this like so
test = self.myObject.something if self.myObject else default_value
Where default_value is whatever you can use as a reasonable default. Thanks to python's short circuit evaluation, this is safe, as the self.myObject.something will never be evaluated if self.myObject is None (or falsey).
Suppose we try to access a non-existing attribute:
>>> {'foo': 'bar'}.gte('foo') # well, I meant “get”!
Python’s AttributeError only has the attribute args with a string containing the finished error message: 'dict' object has no attribute 'gte'
Using the inspect and/or traceback modules with sys.last_traceback, is there a way to get hold of the actual dict object?
>>> offending_object = get_attributeerror_obj(sys.last_traceback)
>>> dir(offending_object)
[...
'clear',
'copy',
'fromkeys',
'get', # ah, here it is!
'items',
...]
Edit: since the cat is out of the bag anyway, I’ll share my findings and code (please don’t solve this and submit to PyPI, please ;))
The AttributeError is created here, which shows that there’s clearly no reference to the originating object attached.
Here the code with the same placeholder function:
import sys
import re
import difflib
AE_MSG_RE = re.compile(r"'(\w+)' object has no attribute '(\w+)'")
def get_attributeerror_obj(tb):
???
old_hook = sys.excepthook
def did_you_mean_hook(type, exc, tb):
old_hook(type, exc, tb)
if type is AttributeError:
match = AE_MSG_RE.match(exc.args[0])
sook = match.group(2)
raising_obj = get_attributeerror_obj(tb)
matches = difflib.get_close_matches(sook, dir(raising_obj))
if matches:
print('\n\nDid you mean?', matches[0], file=sys.stderr)
sys.excepthook = did_you_mean_hook
It's not the answer you want, but I'm pretty sure you can't... at least not with sys.excepthook. This is because the reference counts are decremented as the frame is unwound, so it's perfectly valid for the object to be garbage collected before sys.excepthook is called. In fact, this is what happens in CPython:
import sys
class X:
def __del__(self):
print("deleting")
def error():
X().wrong
old_hook = sys.excepthook
def did_you_mean_hook(type, exc, tb):
print("Error!")
sys.excepthook = did_you_mean_hook
error()
#>>> deleting
#>>> Error!
That said, it isn't always the case. Because the exception object points to the frame, if your code looks like:
def error():
x = X()
x.wrong
x cannot yet be collected. x is owned by the frame, and the frame is alive. But since I've already proven that there is no explicit reference made to this object, it's not ever obvious what to do. For example,
def error():
foo().wrong
may or may not have an object that has survived, and the only feasible way to find out is to run foo... but even then you have problems with side effects.
So no, this is not possible. If you don't mind going to any lengths whatsoever, you'll probably end up having to rewrite the AST on load (akin to FuckIt.py). You don't want to do that, though.
My suggestion would be to try using a linter to get the names of all known classes and their methods. You can use this to reverse-engineer the traceback string to get the class and incorrect method, and then run a fuzzy match to find the suggestion.
Adding my 2 cents as I successfully (so far) tried to do something similar for DidYouMean-Python.
The trick here is that it is pretty much the one case where the error message contains enough information to infer what you actually meant. Indeed, what really matters here is that you tried to call gte on a dict object : you need the type, not the object itself.
If you had written {'foo': 'bar'}.get('foob') the situation would be much trickier to handle and I'd be happy to know if anyone had a solution.
Step one
Check that you are handling an AttributeError (using the first argument of the hook).
Step two
Retrieve the relevant information from the message (using the second argument). I did this with regexp. Please note that this exception can take multiple forms depending on the version of Python, the object you are calling the method on, etc.
So far, my regexp is : "^'?(\w+)'? (?:object|instance) has no attribute '(\w+)'$"
Step three
Get the type object corresponding to the type ('dict' in your case) so that you can call dir() on it. A dirty solution would be just use eval(type) but you can do better and cleaner by reusing the information in the trace (third argument of your hook) : the last element of the trace contains the frame in which the exception occured and in that frame, the type was properly defined (either as a local type, a global type or a builtin).
Once you have the type object, you just need to call dir() on it and extract the suggestion you like the most.
Please let me know if you need more details on what I did.
I wonder how to access the content of the following object with python:
<Quota: (injected_file_content_bytes, 10240)>
I already tried to access the content of my variable called myQuota with myQuota[0] and myQuota.injected_file_content_bytes. None of them worked.
Try dir(myQuota) to see what attributes the object has. Then take it from there (or edit your question to include it) and consider what you can do with it. Alternatively, there must be some documentation explaining what this object contains.
What does the built-in dir function do?
Without arguments, return the list of names in the current local
scope. With an argument, attempt to return a list of valid attributes
for that object.
You can also use __dict__
myQuota.__dict will give you the object attributes in form of key value pairs
I'm refactoring some code, and I thought I could use a bit of Reflection! So, I have this for now:
def f(self, clazz):
[...]
boolean = False
if hasattr(clazz_instace, 'some_attribute'):
setattr(clazz_instace, 'some_attribute', True)
boolean = True
if boolean:
result = getattr(clazz_instace, 'another_method')(None, request=request)
return result['objects']
sorted_objects = getattr(clazz_instace, 'One_more_method')(request)
result = getattr(clazz_instace, 'another_method')(sorted_objects, request=request)
return [...]
My question is about the strings I used to indicate which method I'm searching for regarding to the clazz_instance. I'd like to know if there's another and very best way to do what I did (In a dinamic way to be specific)? I mean, intead of putting method's name like strings directly as I did, would be really nice if I could verify dinamically those methods, differently.
Could you give some nice ideas? How would you do it?
Thanks in advance!!!
An instance's method is nothing more than a function object stored in the instace's __dict__. This said, you are doing correct to find them, except that maybe, the class indeed has the attribute corresponding to your argument string, but is not a function, is just another type instead.
If you depend on this, I recommend you refactor the instance's function looking code into a helper method:
import types
def instance_has_method(instance, name):
try:
attr = getattr(instance, name)
return isinstance(attr, types.FunctionType)
except AttributeError:
return False
Once you have this function, your code will be more concise because now you're sure that the attribute is indeed a function and can be callable.
The code above checks if the attribute is a function. If you want something wider, you can check if it's a callable like this: return hasattr(attr, '__call__').
In python, this is basically how you check for attributes inside classes. I don't think there's nothing wrong with your approach and not another more clever way to do reflection.
Hope this helps!
It's not easy to understand what you are trying to achieve.
getattr(clazz_instace, 'One_more_method')(request) is just a fancy way to say clazz_instace.One_more_method(request).
Use of getattr is reasonable when you don't know the method name in advance, that is, if your method name is variable.
Also, setattr(clazz_instace, 'some_method_inside_this_class', True) turns alleged some_method_inside_this_class into a scalar attribute inside that class, having a True value. Probably this is not what you planned to have.
My best effort to understand your code is this:
def f(clazz):
# if clazz is capable of better_processing, use it:
if hasattr(clazz, 'better_processing'):
return clazz.better_processing(...)
else:
return clazz.basic_processing(...)
BTW what getattr gives you is a callable method, you can directly use it, like this:
method = getattr(clazz, 'better_method', clazz.default_method)
# if 'better_method' was available, it was returned by getattr;
# if not, the default method was returned.
return method(clazz_instance, some_data...)