I'm trying to write the output of an API 'get' request to a file. I know the function works as the output of the request is returned successfully and in full in shell.
The function creates the file, but the file only includes the status code for the get request - can anyone help me understand why? Still pretty new to Python and very new to calling APIs...
def user_info(token):
heads = {"Authorization": "bearer " + token, "Content-type": "application/json"}
url = "xxxxx"
request = req.get(url, headers=heads)
with open('userdata.txt', 'w') as f:
f.write(str(request))
if request.status_code == 200:
return request.json()
else:
return "User Info FAILED! Failure code: {}, error: {}".format(request.status_code,request.json()['error'])
The file just contains:
<Response [200]>
Thanks!
A Response object in the requests module when called as a string will return its status code as detailed in the Response python code
def __repr__(self):
return '<Response [%s]>' % (self.status_code)
If you want to write the json from the response as a string then you can use the built in json module and use its dumps method to dump it as a string not a dict.
import requests
import json
with open("myfile.txt", "w") as output:
resp = requests.get("https://jsonplaceholder.typicode.com/todos/1")
output.write(json.dumps(resp.json()))
Related
I wrote endpoint called foobar in default.py controller of web2py, it looks like
#service.json
def foobar(*args, **vars):
payload = request.vars.student
print(payload)
#Above payload prints [rollNo, firstName, lastName]
#Expected is {"rollNo": 6299857, "FirstName": Prasad, "LastName": Telkikar}
fileObj= request.vars.video
studentActivity = fileObj.file.read()
#Currently I am unable to do it from unit test, but it works from postman
print(f"Student's Roll number = {payload.rollNo} \n FirstName = {payload.firstName}, \n lastName = {payload.lastName}, fileSize = {fileObj.file.tell()}")
#storing studentActivity video to specific location
#Doing business logic
Now I am writing unit test for this endpoint, where i am trying to call this endpoint using requests,
import requests
import unittest
...
class TestStudentsData(unittest.TestCase):
def test_Individual_student(self):
payload = dict(rollNo=6299857, firstName="Prasad", lastName="Telkikar")
url = "http://127.0.0.1:8000/v1/foobar"
header = dict(Authorization="Bearer <Token>")
response = requests.post(url,files={'studentActivity':open("Activity.mp4", 'rb')}, data=payload, headers=headers)
self.assertEqual(response.status_code, 200)
if __name__ == '__main__':
unittest.main(verbosity=2)
Here I am unable to pass student payload as a json.
How can I pass json payload with studentActivity file using requests?
What I tried so far?
I tried both the approaches given in this SO answer.
I read requests documentation where it says "the json parameter is ignored if either data or files is passed" requests documentation
I resolved this problem by adding proper content-type to payload,
import os
...
filePath = os.getcwd()
files = {'studentActivity':open(filePath, "Activity.mp4", 'rb'),
'payload':(None, payload, 'application/json')}
#^^^^^^^^^^^^^^^^^ This was missing
response = requests.post(url,files={'studentActivity':open("Activity.mp4", 'rb')}, data=payload, headers=headers)
I have the following python function where im trying to upload a file over to an API that accepts a file as multipart stream. The API correctly works with postman, however im struggling to identify the problem here.
I have parameters (json body) to post to the API along with the file which I have tried to encode inside my mp_encoder variable.
def callAPIwithFile(apiData,apiUrl):
file_ids = ''
jsonData = {'type':apiData['type'],'fromId':apiData['fromid'],'toUserIds':apiData['userIds'],'toGroupIds1':apiData['groupIds'],'toDepartmentIds1':apiData['departmentIds'],'subject':apiData['subject'],'body':apiData['body'],'attachment':apiData['attachment'],'report':apiData['report']}
mp_encoder = MultipartEncoder(fields={'type':apiData['type'],'fromId':apiData['fromid'],'toUserIds':apiData['userIds'],'toGroupIds1':apiData['groupIds'],'toDepartmentIds1':apiData['departmentIds'],'subject':apiData['subject'],'body':apiData['body'],'attachment':apiData['attachment'],'report':apiData['report'],'file': (apiData["attachment"], open(apiData["attachment"], 'rb'), 'application/vnd.ms-excel')})
print mp_encoder
headers = {'Authorization': 'Bearer jwt'}
resp = requests.post(apiUrl,headers=headers,data=mp_encoder)
print resp.text
print "status code " + str(resp.status_code)
if resp.status_code == 201:
print ("Success")
data = json.loads(resp.text)
file_ids = data['file_ids']
print file_ids
else:
print ("Failure")
On running the code I get the following errors :
{"statusCode":400,"message":["type must be a valid alpha, beta, Or gamma","body should not be empty"],"error":"Bad Request"}
status code 400
Failure
As per my understanding the JSON Body that im trying to post to the API is not being recognised correctly. How do I go about this?
Please note, I have tried using request.post(apiUrl,file=files,data=data,header=header) which results in an error of unexpected field.
The below answer could solve my problem :
headers = {'Authorization': 'Bearer '+token}
mydict = dict(type=apiData['type'], fromId=apiData['fromid'], toUserIds1=apiData['userIds'], toGroupIds=apiData['groupIds'], toDepartmentIds1= apiData['departmentIds'], subject= apiData['subject'], body= apiData['body'], attachment= apiData['attachment'], report= apiData['report'])
resp=requests.post(apiUrl, headers = headers, files=dict(attachment=(apiData["attachment"], open(apiData["attachment"], 'rb'), 'application/vnd.ms-excel')),data=mydict)
While implementing a rest API in python flask, I have used several options to return a file (any type) , read it and save it to local repository of request but encountered with multiple errors as below:
Case 1:
def download_file():
return send_file('any_file.pdf')
r = requests.get(url = 'http://localhost:5000/download').read()
has responded with a error Response object has no attribute read/text/content
Case 2:
def download_file():
file = open('any_file.pdf','r').read()
return file
r = requests.get(url = 'http://localhost:5000/download')
has responded with a error Return doesn't accept this
So How can I do this as flask is not allowing to return a file without response object and response object is not readable and doesn't support to save that file directly.
The Flask server code in Case 1 is correct. A more complete example:
#app.route('/download')
def download_file():
# Some logic here
send_file('any_file.pdf')
However the Response object returned by requests.get doesn't have a read method. The correct way is to use:
Response.content: Content of the response, in bytes.
So, the client code should be:
r = requests.get('http://localhost:5000/download')
bytes = r.content
# Now do something with bytes, for example save it:
with open('downloaded_file.ext', 'wb') as f:
f.write(bytes)
I am trying to adapt this script so that even if multiple messages are sent at the same time the script will just keep trying until they are let through.
The original script is: https://github.com/4rqm/dhooks
My version is:
def post(self):
"""
Send the JSON formated object to the specified `self.url`.
"""
headers = {'Content-Type': 'application/json'}
result = requests.post(self.url, data=self.json, headers=headers)
if result.status_code == 400 or result.status_code == 429:
print(result.status_code)
#its the line below that does not work.
post(self)
else:
print("Payload delivered successfuly")
print("Code : "+str(result.status_code))
time.sleep(2)
the function looks like this:
import requests
import json
def parse(s):
r = requests.post('http://166.111.139.15:9000/?properties%3d%7b%22annotators%22%3a%22tokenize%2cssplit%2cpos%2clemma%2cparse%22%2c%22outputFormat%22%3a%22json%22%7d%0a', data=s)
return r.json()
print parse("I am a student")
And when I use it in Django, the web page shows:
"No JSON object could be decoded".Why?
No JSON object could be decoded is an exception message raised at r.json(). If your response is not a valid json object you can still retrieve it with r.text. Even if you are sure your response is always a valid json object, you should still check whether server returned a success code. If there's an internal server error (code 500), you won't get a valid json response!
import requests
def parse(s)
r = requests.post('http://someserver.com', data=s)
if r.status_code !== 200:
return "There was a problem: {} !".format(r.text)
return r.json()