pass a string in python requests - python

I have a function which require to pass some ids as comma seperated to the url string.
My code:
def shipment(self, orderItemIds):
url = "https://api.flipkart.net/sellers/orders/shipments"
payload = {'orderItemsIds':orderItemIds}
return self.session.get(url, data=payload)
I need to pass id1, id2, id3 so that i get a link as:
https://api.flipkart.net/sellers/orders/shipments?orderItemsIds={id1,id2...}
I tried to pass it as a string. and as a list too. But it didn't worked.
oid = 'id1,id2,id3' # or
oid = ['id1',id2'','id3']
How to do it?
I passed an id as oiids = '230501592'.
On running response.url, it gives me:
https://api.flipkart.net/sellers/orders/shipments?orderItemsIds
It shows that parameter values are not passing in the url string.

I believe what you want is this (where orderItemIds is a list of strings):
def shipment(self, orderItemIds):
url = "https://api.flipkart.net/sellers/orders/shipments"
params = {'orderItemsIds': ','.join(orderItemIds)}
return self.session.get(url, params=params)
The differences from the version you have in the question are that orderItemIds is assumed to be a list of strings and is being joined with commas, and the data keyword is replaced with params, which is the right choice for a GET request.

You can easily send get parameters in python requests library-
data = {
'orderItemsIds': ['id1', 'id2', 'id3']
}
response = requests.get(url, data = data)

Related

Update dictionary value for a particular key with value from iterator of outer loop

I have a list of lists in this format:
nrows = ["['Shock pain', 'attack sharp pain']",
"['bruises', 'lump']",
"['fever', 'cold', 'Anxiety']",
"['neck pain', 'headache']"]
I want to call an API by passing everytime 1 list at a time from the nrows list. Each list should be passed 1 by 1 to the data dict with key sList and the response should be saved.
The API function is as follows:
newres = []
for i in nrows:
url = "https://testabcd.io"
data= {
"sList": i,
"kList" : ["age"],
}
headers = {
'Content-Type': 'application/json',
'Auth': '0644427814339900'
}
response = requests.request("GET", url, headers=headers, json=data)
newres.append(response.text)
print(response.text)
print(newres)
Inside the data dict, in sList, at each iteration, I want to pass 1 sublist at a time and get the response appended in a list.
The current code has all the response same as I think I am unable to iterate and change the value of the data dict with key sList which is what is expected.
The csv looks like this:
['Shock pain', 'attack sharp pain']
['bruises', 'lump']
['fever', 'cold', 'Anxiety']
Assuming the file you work with, really looks like this:
['Shock pain', 'attack sharp pain']
['bruises', 'lump']
['fever', 'cold', 'Anxiety']
you can use ast.literal_eval in order to convert the line from the file into list
import requests
from ast import literal_eval
newres = []
url = "https://testabcd.io"
headers = {'Content-Type':'application/json',
'Auth':'0644427814339900'}
with open("yourfile") as f:
for line in f:
data= {"sList": literal_eval(line),
"kList" : ["age"]}
response = requests.get(url, headers=headers, json=data)
newres.append(response.text)
print(response.text)
print(newres)
Note:
This is not tested.
Given that your data comes from non-standard file, where they were exported in bad manner from a dataframe, created unknown how - I would suggest that you seriously reconsider all your workflow and how you manipulate your data.

Run single python method many times simultaneously

I have a method which takes one argument, and post to a host.
def fts(searchstring):
search_string="\""+searchstring+"\""
headers = {'Content-Type': 'application/json',}
data = '{ "explain": true,"fields": ["*"],"highlight": {},"query": { "query": '+search_string+'},"size":0}'
response = requests.post('hostname', headers=headers, data=data, auth=('uname', 'password'))
if response.status_code != 200:
raise Exception("{} - {}".format(response.status_code, response.text))
print(response.json())
I want to run this method in several processes at a time with different arguments. Is this possible? I tried to use multiprocessing but couldn't able to get it.
Thanks
Code pool.map(fts, searchstring) will run simultaneously but it will treat searchstring as list of chars and send every single char to different fts
You need list with all strings
all_results = pool.map(fts, [searchstring1, searchstring2, searchstring3, ...])
BTW: If you will need to send more arguments then you will need list with tuples or sublists.
all_results = pool.map(fts, [(searchstring1, param1), (searchstring2, param2), ...])
and define function as
def fts(args):
searchstring, param = args

What's the difference between '{"title":"some title", "body":"some body"}' and '{"title":title, "body":body}', when title and body are string values?

Code below works:
r = requests.post(url = myurl, data = '{"title":"sometitle", "body":"some body"}')
But this code doesn't work:
t = "title"
b = "body"
r = requests.post(url = myurl, data = '{"title":title, "body":body}')
The second one causes 400 error.
I can't find any meaningful difference.
What I changed is just replacing " " string to a string value.
According to requests doc, data is
data – (optional) Dictionary, list of tuples, bytes, or file-like
object to send in the body of the Request.
I have to get some values and store them into variables, so I need to make the code in the second way.
How can I resolve this?
data – (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request.
In both cases you are not passing a dictionary. You are passing a string both times.
r = requests.post(url = myurl, data = '{"title":"sometitle", "body":"some body"}')
This is a dictionary parsed into a string.
t = "title"
b = "body"
r = requests.post(url = myurl, data = '{"title":title, "body":body}')
This is a non-valid dictionary parsed into a string. You probably meant to write:
t = "title"
b = "body"
r = requests.post(url = myurl, data = {"title":title, "body":body})
Which is equivalent to:
r = requests.post(url = myurl, data = {"title":"title", "body":"body"})
Here you would be passing a dictionary and you can also reference variables. It is not a string you are passing.
If you require the data to be in a string format (which doesn't make sense since the documentation you referenced says it requires a dictionary) you do:
t = "title"
b = "body"
r = requests.post(url = myurl, data = json.dumps({"title":title, "body":body}))

TypeError: byte indices must be integers

I want to get the top artists from a specific country from the last fm API in JSON and save the name and url in the name and url variables. But it always appears "TypeError: byte indices must be integers". Do you know where is the issue?
Working example:
import requests
api_key = "xxx"
for i in range(2,5):
artists = requests.get('http://ws.audioscrobbler.com/2.0/?method=geo.gettopartists&country=spain&format=json&page='+str(i)+'&api_key='+api_key)
for artist in artists:
print(artist)
#name = artist['topartists']['artist']['name']
#url = artist['topartists']['artist']['url']
You want:
response = requests.get(...)
data = response.json()
for artist in data["topartists"]["artist"]:
name = artist["name"]
# etc
Explanation: requests.get() returns a response object. Iterating over the response object is actually iterating over the raw textual response content, line by line. Since this content is actually json, you want to first decode it to Python (response.json() is mainly a shortcut for json.loads(response.content)). You then get a python dict with, in this case, a single key "topartists" which points to a list of "artist" dicts.
A couple hints:
First you may want to learn to use string formatting instead of string concatenation. This :
'http://ws.audioscrobbler.com/2.0/?method=geo.gettopartists&country=spain&format=json&page='+str(i)+'&api_key='+api_key
is ugly and hardly readable. Using string formatting:
urltemplate = "http://ws.audioscrobbler.com/2.0/?method=geo.gettopartists&country=spain&format=json&page={page}&api_key={api_key}"
url = urltemplate.format(page=i, api_key=api_key)
but actually requests knows how to build a querystring from a dict, so you should really use this instead:
query = {
"method": "geo.gettopartists",
"country":"spain",
"format":"json",
"api_key": api_key
}
url = "http://ws.audioscrobbler.com/2.0/"
for pagenum in range(x, y):
query["page"] = pagenum
response = requests.get(url, params=query)
# etc
Then, you may also want to handle errors - there are quite a few things that can go wrong doing an HTTP request.

Printing out a Python List with unknown contents

def enumerate_all_config_objects(baseDN):
url = 'https://www.AwebsiteThatIWontProvide.com'
payload={"ObjectDN":baseDN,"Pattern":"*aws*","Pattern":"*jkb*"}
r = requests.post(url, verify='/PathToKeyForVerification/', headers=headers,data=json.dumps(payload))
response = r.json()
status = r.status_code
print " "
print "Returned status code:", status
print " "
return response ['Objects'][0]['GUID']
Output:
Returned status code: 200
{11871545-8c5b-4c3c-9609-7372fae1add5}
Process finished with exit code 0
I am trying to return ONLY the "GUID" information from a json request. This works (the 1187154...), as I enter values into the index between ['objects'] and ['guid'], each value is successfully produced from the list. My problem is, even though I am printing out the actual response to verify the output is correct, the final script should not require anything being dumped to a CSV file. I have to perform everything in memory. The next function that I need to create will use the returned GUID values and query the server with those values.
How do I get the items in the list to display from the output of enumerate_all_config_objects? I would like to print them to troubleshoot initially. Then I will comment out this feature and have the second function pull each value from that list and use it.
Two problems:
Print out the list which will always have an unknown number of entries.
Create another function to reference / use the values from that list.
The list is populated correctly, I've verified this. I just don't know how to access it or print it.
If I understood correctly, you are looking to do something like:
def enumerate_all_config_objects(baseDN):
url = 'https://www.AwebsiteThatIWontProvide.com'
payload = {"ObjectDN": baseDN, "Pattern": "*aws*", "Pattern": "*jkb*"}
r = requests.post(url, verify='/PathToKeyForVerification/', headers=headers,data=json.dumps(payload))
response = r.json()
status = r.status_code
return map(lambda x: x["GUID"] , response['Objects'])
def use_guids(guid_list):
#do_stuff, for example, to show the guids:
for guid in guid_list:
print(guid)
use_guids(enumerate_all_config_objects(baseDN=<replaceWithYourParameter>))
Edit : To clear out the questions from your comment, I decided to mock the call to the API which you said already works
def enumerate_all_config_objects():
foo = {"GUID" : 1}
bar = {"GUID" : 2}
baz = {"GUID" : 3}
response = {"Objects": [foo, bar, baz] }
mapped = list(map(lambda x: x["GUID"] , response['Objects']))
return map(lambda x: x["GUID"] , response['Objects'])
def use_guids(guid_list):
#do_stuff, for example, to show the guids:
for guid in guid_list:
print(guid)
use_guids(enumerate_all_config_objects())
prints out
1
2
3
When you want to use the value computed from a function, you need to use the return keyword.
For example return map(lambda x: x["GUID"] , response['Objects']), in this new example would return a map object containing [1, 2, 3]. This return value can then be used such as in my first example by passing it to another function.
In the example just above, the list is passed to the use_guids function, which prints the contents of the list.
Edit 2 : If you really insist on calling a function that handles one GUID, you can do that in this way:
def enumerate_all_config_objects(baseDN):
url = 'https://www.AwebsiteThatIWontProvide.com'
payload = {"ObjectDN": baseDN, "Pattern": "*aws*", "Pattern": "*jkb*"}
r = requests.post(url, verify='/PathToKeyForVerification/', headers=headers,data=json.dumps(payload))
response = r.json()
status = r.status_code
for obj in response['Objects']:
use_guid(obj["GUID"])
def use_guid(guid):
print(guid)
# Do some other stuff.
# ...
enumerate_all_config_objects(baseDN=<replaceWithYourParameter>)

Categories