I am using a scraper to upload json data to a database but I noticed that my uploads are not in order yet my local json data file FILE_PATH mirroring the database has my json data in order, meaning that the culprit is in how I use python's request module.
def main():
if not FILE_PATH.is_file():
print("initializing json database file")
# intialize and reverse the dictionary list in one go, [start:stop:step]
ref_links = getArchivedCharacterList()[::-1]
index =0 # counting up the roster size for assignReleasedate
for link in ref_links:
char_details = getCharacterDetails(link['ref_id'],link['game_origin'],index)
index +=1
saveCharacterInfo(char_details)
postRequest(POST_CHARA_DETAILS_URL,char_details,headers)
print(f"Done! Updated the file with all previously released and archived units as of: \n {datetime.datetime.now()} \n See {FILE_PATH} for details!")
From the above, I initially scrape a page for a list of links using getArchivedCharacterList(), then for each link, I grab more information for individual pages and then I post them into my local file FILE_PATH using saveCharacterInfo and I POST it into my database with the postRequest function.
postRequest function
def postRequest(url,json_details,headers):
r = requests.post(url, json=json_details, headers=headers)
while r.status_code != 201:
time.sleep(0.1)
print(r.status_code)
I tried doing a while function to wait for the 201 POST success response. Didn't work. I looked up async/await tutorials and it doesn't seem like something I want... unless I am supposed to bundle up all my request posts in a single go? I did this before in javascript where I bundled up all my posts in a promise array is there a promise equivalent for python from javascript so that I do my uploads in order? Or is there another method to achieve a sequential upload?
Thank you in advance!
i'm trying to create a script to download a test excel (.xlsx) file. The script does output a 'test'.xlsx file, but it contains the following error message instead of the actual file contents.
Bad Request
Your browser sent a request that this server could not understand.
Additionally, a 400 Bad Request error was encountered while trying to use an ErrorDocument to handle the request.*
I did manage to download the test file using urllib, however would like to use requests instead as I require authentication for my actual use case. Here's the code i used, do let me know what's wrong, thanks!
import requests
dls = "http://www.excel-easy.com/examples/excel-files/fibonacci-sequence.xlsx"
resp = requests.get(dls)
output = open('test.xlsx', 'wb')
output.write(resp.content)
output.close()
I try to use falcon package in my project. Problem is I didn't find a way to get body data from the HTTP post request.
I used code from example, but req.stream.read() doesn't return JSON as expected.
The code is:
raw_json = req.stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')
How to get the POST data?
Thanks for any help
in falcon 2, if you work with json type, use req.media
for example:
import falcon
from json import dumps
class Resource(object):
def on_post(self, req, resp, **kwargs):
result = req.media
# do your job
resp.body = dumps(result)
api = falcon.API()
api.add_route('/test', Resource())
Little digging into the problem led to the following linked issue on github. It states that falcon framework at least in its version 0.3 and working with Python 2 didn't parse data 'POSTed' as string if they are aptly escaped. We could use more information on what data you are trying to send over POST request and in what format is that being sent, as in if its being send as simple text, or with Header Information Content-Type:application/json, or if its coming through an HTML form.
While the exact issue is not clear from the question I could still suggest trying to use bounded_stream instead of stream as in:
raw_json = req.bounded_stream.read()
result.json(raw_json, encoding='utf-8')
resp.body = json.dumps(result_json, encoding='utf-8')
for the official documentation suggests use of bounded_stream where uncertain conditions such as Content-Length undefined or 0, or if header information is missing altogether.
bounded_stream is described as the following in the official falcon documentation.
File-like wrapper around stream to normalize certain differences between the native input objects employed by different WSGI servers. In particular, bounded_stream is aware of the expected Content-Length of the body, and will never block on out-of-bounds reads, assuming the client does not stall while transmitting the data to the server.
Falcon receives the HTTP requests data as buffer object as passed by WSGI wrapper which receives the data from client, and its possible it doesn't run proper parsing on top of the data to convert to a more usable data structure for performance reasons.
Big thanks to Ryan (and Prateek Jain) for the answer.
The solution is simply to put app.req_options.auto_parse_form_urlencoded=True. For example:
import falcon
class ThingsResource(object):
def on_post(self, req, resp):
value = req.get_param("value", required=True)
#do something with value
app = falcon.API()
app.req_options.auto_parse_form_urlencoded=True
things = ThingsResource()
app.add_route('/things', things)
The field you're looking for is somewhat confusingly named, but it's req.media:
Returns a deserialized form of the request stream. When called, it will attempt to deserialize the request stream using the Content-Type header as well as the media-type handlers configured via falcon.RequestOptions.
If the request is JSON, req.media already contains a python dict.
I have added changes in request.py in falcon framework to parse application/x-www-form-urlencoded and multipart/from-data.
I have raised pull request - https://github.com/falconry/falcon/pull/1236 but it is not yet merged in master.
Check this - https://github.com/branelmoro/falcon
I have added new code to parse POST, PUT and DELETE application/x-www-form-urlencoded and multipart/form-data.
Text fields will be available in req.form_data dictionary and upload file buffer stream will be available in req.files dictionary.
I hope this will help to access POST and GET parameters separately and we will be able to upload files as well.
Good thing about the change is that it will not load entire uploaded file in memory.
Below is sample code to show how to use POST, PUT and DELETE application/x-www-form-urlencoded and multipart/form-data:
import falcon
class Resource(object):
def on_post(self, req, resp):
# req.form_data will return dictionary of text field names and their values
print(req.form_data)
# req.form_data will return dictionary of file field names and
# their buffer class FileStream objects as values
print(req.files)
# support we are uploading a image.jpg in `pancard` file field then
# req.files["pancard"] will be FileStream buffer object
# We can use set_max_upload_size method to set maximum allowed
# file size let say 1Mb = 1*1024*1024 bytes for this file
req.files["pancard"].set_max_upload_size(1*1024*1024)
# We can use uploadto method to upload file on required path (Note: absolute filepath is required)
# This method returns boolean - `True` on successful upload
# and if upload is unsuccessful then it returns `False` and sets error on failure.
path = "/tmp/" + req.files["pancard"].name
response = req.files["pancard"].uploadto("/tmp/" + path)
print(response)
# Once file is uploaded sucessfully, we can check it's size
print(req.files["pancard"].size)
# If file is not uploaded sucessfully, we can check it's error
print(req.files["pancard"].error)
resp.body = "Done file upload"
resp.status = falcon.HTTP_200
# falcon.API instances are callable WSGI apps
app = falcon.API()
things = Resource()
# things will handle post requests to the '/post_path' URL path
app.add_route('/post_path', things)
Do let me know if you have any doubts.
So far... for me bounded_stream.read() and stream.read() both get the posted data as type str. I have only found one way around the issue so far:
def on_post(self, req, resp):
posted_data = json.loads(req.stream.read())
print(str(type(posted_data)))
print(posted_data)
Loading the string into a json dict once the posted data is received is my only solution that I can come up with
Here's something I used while designing an API.
import falcon
import json
class VerifierResource():
def on_post(self, req, resp):
credentials = json.loads(req.stream.read())
if credentials['username'] == USER \
and credentials['passwd'] == PASSWORD:
resp.body = json.dumps({"status": "verified"})
else:
resp.body = json.dumps({"status": "invalid"})
api = falcon.API()
api.add_route('/verify', VerifierResource())
This returns a serialized JSON with corresponding response body.
there is a sample way to get media from body. I use to get the body in the post method:
def on_post(req,resp)
arguments = {}
# get body media on post method
body = req.get_media()
if 'something' in body:
arguments['something'] = body['something']
send body content type Media-Type and print resp or use in code, but if want to send JSON body your code should cover give JSON parameters.
Do let me know if you have any doubts.
I'm making website using AngularJS and Flask.
AngularJS controller, some_controller.js posts JSON data to /url.
And in flask, I want to get data and use it like below.
#route('/url')
def somefunction():
filter = json.loads(request.data)
namefilter = filter.get('name', '')
But it doesn't work so I want to log whether filter gets correct data or not.
How can I log filter in console?
Angular should send the data back with the correct content-type header, so you should be able to just use
payload = request.json
print payload
#if using py3 print(payload)
If you are looking to do so from the Angular side, then you can use
console.log('filter log' + filter);
or the custom $log provider.
I am new to SOAP and suds. I am calling a non-XML SOAP API using suds. A given result contains a ton of different sub-arrays. I thought I would just locally save the whole response for parsing later but easier said than done. And I don't get this business with the built in cache option where you cache for x days or whatever. Can I permanently save and parse a response locally?
You can write the response to a local file:
client = Client("http://someWsdl?wsdl")
# Getting response object
method_response = client.service.someMethod(methodParams)
# Open local file
fd = os.open("response_file.txt",os.O_RDWR|os.O_CREAT)
# Convert response object into string
response_str = str(method_response)
# Write response to the file
ret = os.write(fd,response_str)
# Close the file
os.close(fd)