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.
Related
I have a strange problem and I can't seem to find a solution. I'm creating a Python app that sends a get request to an endpoint, fetches some data in JSON format and processes it to insert it into a database later. I have to classes, one is like APIClient, and the other is just a namespace to hold some methods to transform the data, let's call it APITransform.
There is a problematic method in APITransform, so here's the code.
#api.py module"
class APITransform:
...
#staticmethod
def flatten(data:dict, method:str):
if method == "some flattening method from a config file":
return list(data.values())
....
class APIClient:
....
def get_data():
....
response = requests.get(URL, headers, params)
json_resp = response.json()
json_resp = APITransform.flatten(
json_resp, "some flattening method from a config file")
#main.py module
from api import APIClient
api_client = APIClient()
api_client.get_data()
The error traces to APITransform.flatten() with the message:
return list(data.values())
AttributeError: 'list' object has no attribute 'values'
EDIT: The strange thing is that If I print the type of json_resp object before passing it to APITransform.flatten() in get_data(), I get two outputs in two lines: <class dict> and <class list>. It's like get_data() is being called twice, but I searched it in the entire project, I can only find it in two places, the definition in APIClient and call in main.py. I'm out of debugging ideas.
Anyone with an idea? Thanks
the code can raise such an error if the result of the json which is returned from a server, is a list, for example, if the response (from the server) is something like "[1,2,3]" or any other json list, the json_resp variable would be a list, that of course has no values() function. make sure the server returns the data in proper format or use an if statement to check before passing to the flatten function.
I am trying to test a function which contain an API call. So in the function I have this line of code :
api_request = dict(requests.get(url_of_the_API).json())
So I tried to use patch like this :
#patch('requests.get')
def test_products_list_creator(self, mock_get):
mock_get.return_value = json.dumps({"products":
{
"name": "apple",
"categories": "fruit,red"
}
})
But at the line of my API call, python throw me this error :
AttributeError: 'str' object has no attribute 'json'
I tried to print type(requests.get(url_of_the_API}.json")) to know what it was and I got this : <class 'requests.models.Response'>
There is a lot of questions about convert a Response in dict but didn't found any about converting a dict to a Response.
So how to make my patch callable by the method json() ?
Firstly we need to figure what is required by requests.models.Response's method .json in order to work, this can be done by scrying source code available at github - requests.models source. After reading requests.models.Response.json body we might conclude that if encoding is set, it does simply loads .text. text method has #property decorator, meaning it is computed when accessing .text, this in turn depend on .content which also is computed. After scrying .content it should be clear that if we set ._content value then it will be returned by .content, therefore to make fake Response which do support .json we need to create one and set .encoding and ._content of it, consider following example:
from requests.models import Response
resp = Response()
resp.encoding = 'ascii'
resp._content = b'{"x":100}'
print(resp.json())
output
{'x': 100}
Note that _content value needs to be bytes so if you have dict d then to get value to be put there do json.dumps(d).encode('ascii')
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]
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.
I have a response from a URL which is of this format.
'history': {'all': [[u'09 Aug', 1,5'],[u'16 Aug', 2, 6]]}
And code is :
response = urllib.urlopen(url)
data = json.loads(response.read())
print data["fixture_history"]['all']
customObject = MyObject (
history = data["history"]['all']
)
Printing works but in my custom class I am seeing this error :
history = data["history"]['all']
TypeError: 'module' object is not callable
My class is :
class MyObject:
#init
def _init_(self,history):
self.hstory = history
Printing works but in my custom class I am seeing this error :
TypeError: 'module' object is not callable
I bet your your class is defined in a module named MyObject.py and that you imported it as import MyObject instead of from MyObject import MyObject, so in your calling code, name MyObject is bound to the module, not the class.
If you Class is defined in a different Module please make sure that that you have imported it the right way ie. you need to use from X import Y format but not Import X and expect it to work as if we do it that way we need to let python know the module we are calling it from.
And i am not very sure but i think the typo in the constructor might case the issue as stated
bigOTHER