This question already has an answer here:
Testing code that requires a Flask app or request context
(1 answer)
Closed 5 years ago.
First of all, I am very new at programming.
I am trying to save a variable from bash shell
>curl http://169.254.169.254/latest/meta-data/
this line would return data such as local-ipv4. And I am trying to use phython and flask to save those variables. I wrote
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def testRequest():
url1 = "http://169.254.169.254/latest/meta-data/"
name1 = request.get(url1)
nameText = name1.text
return nameText
testOutput = testRequest()
print testOutput
But this gives me runtime error : working outside of the request context.
can someone guide me to where to look for possible solution?
To things to comment here:
First, it seems that you'll be just fine by using requests, a highly recommended library for HTTP requests. With it you could do:
import requests
url = "http://169.254.169.254/latest/meta-data/"
resp = requests.get(url)
print resp.text
Regards to the error you're getting runtime error : working outside of the request context, is because by testOutput = testRequest() you're calling a method that's part of the Flask app app. Another thing related to the error is that you never ran the Flask app. To do this, include this at the end of your code.
if __name__ == '__main__':
app.run()
But again, Flask is rather a web framework that it's useful to create web sites, APIs, web apps, etc. It's very useful, but I don't think you may need it for what you're trying to achieve.
Further info about requests and Flask:
http://docs.python-requests.org/
http://flask.pocoo.org/
Since you only need to make an HTTP GET request and print the response, you don't need Flask. You can use the urllib standard library to send the GET request (https://docs.python.org/3/library/urllib.request.html):
import urllib.request
def testRequest():
url1 = "http://169.254.169.254/latest/meta-data/"
response = urllib.request.urlopen(url1)
nameText = response.read().decode('utf-8')
return nameText
testOutput = testRequest()
print testOutput
Related
This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 3 years ago.
I have a small flask API setup as following,
from flask import Flask, request, jsonify, Response
import json
import subprocess
import os
app = Flask(__name__)
shellScripts = {
'redeploy': ['/bin/bash', 'redeploy.sh'],
'script-exec': ['/bin/bash', 'script-exec.sh']
}
def prepareShellCommand(json_data, scriptKey):
script=shellScripts[scriptKey]
print('script is')
print(script)
for key in json_data:
if scriptKey == 'redeploy':
script.append("-{0}".format(key[0]))
script.append(json_data[key])
return script
#app.route('/redeploy', methods=['POST'])
def setup_redeploy():
branches_data_json = request.get_json()
if ('frontendBranch' not in branches_data_json and 'backendBranch' not in branches_data_json):
return jsonify({'error': 'Need to provide at least one branch'}), 400
command = prepareShellCommand(branches_data_json, 'redeploy')
sp = subprocess.Popen(command)
return jsonify({'message': 'Redeployment under process'}), 201
#app.route('/execute', methods=['POST'])
def execute_script():
script_data_json = request.get_json()
if ('scriptPath' not in script_data_json):
return jsonify({'error': 'Need to provide script path'}), 400
command = prepareShellCommand(script_data_json, 'script-exec')
sp = subprocess.Popen(command)
return jsonify({'message': 'Script execution under process'}), 201
What's happening is, say I initiate an API endpoint, /execute with some data as {scriptPath: 'some-file'}, and it runs successfully. However, sometimes, regardless of change in the request body data, the API seems to work with the old data, {scriptPath: 'some-file'}, even if I am initiating the API with something like {scriptPath: 'new-file'}. And it doesn't change until I kill the python process, and restart it.
What could be the reason for this? I am running this as a development server, on a google cloud instance.
It's happening with both the endpoints, and I have a gut feeling that it's got something to do with either the subprocess or the dictionary that contains the boilerplate.
Can anyone help me with this?
This is almost certainly because you have defined shellScripts at module level but modify it from your handlers. The changes to the values of that dictionary will persist for the lifetime of the server process.
You should copy the value and modify that instead:
def prepareShellCommand(json_data, scriptKey):
script = shellScripts[scriptKey].copy()
the api should include one function called "write text to file" and inputs a string parameter
as for the function to write to the disk I have no problem and I implemented the code my problem is how to set the rest API using python.
EDIT:
this is my code:
from flask import (
Flask,
render_template
)
import SocketServer
import SimpleHTTPServer
import re
app = Flask(__name__, template_folder="templates")
#app.route('/index', methods=['GET'])
def index():
return 'Welcome'
#app.route('/write_text_to_file', methods=['POST'])
def write_text_to_file():
f = open("str.txt", "w+")
f.write("hello world")
f.close()
if __name__ == '__main__':
app.run(debug=True)
anyhow when I try to test my rest api:
http://127.0.0.1:5000/write_text_to_file
I am getting the following error:
Now I'm trying to test my rest-api , however how can I make my code to start the server and to the test the post request api, this is my test_class:
import requests
import unittest
API_ENDPOINT="http://127.0.0.1:5000/write_text_to_file"
class test_my_rest_api(unittest.TestCase):
def test_post_request(self):
"""start the server"""
r = requests.post(API_ENDPOINT)
res = r.text
print(res)
also when runnning my request using postman I am getting internal_server_error:
You're doing a GET request for this url, but you've specified that this endpoint can only accept POST:
#app.route('/write_text_to_file', methods=['POST'])
Also, the SocketServer and SimpleHTTPServer imports are not needed with Flask.
The method is not allowed because Chrome (or any browser) makes GET requests.
Whereas, you defined it as POST
#app.route('/write_text_to_file', methods=['POST'])
Either change it to a GET method, or use a tool such as POSTMan to perform other HTTP call types
this is a two-part question: I have seen individual pieces discussed, but can't seem to get the recommended suggestions to work together. I want to create a web service to store images and their metadata passed from a caller and run a test call from Postman to make sure it is working. So to pass an image (Drew16.jpg) to the web service via Postman, it appears I need something like this:
For the web service, I have some python/flask code to read the request (one of many variations I have tried):
from flask import Flask, jsonify, request, render_template
from flask_restful import Resource, Api, reqparse
...
def post(self, name):
request_data = request.get_json()
userId = request_data['UserId']
type = request_data['ImageType']
image = request.files['Image']
Had no problem with the data portion and straight JSON but adding the image has been a bugger. Where am I going wrong on my Postman config? What is the actual set of Python commands for reading the metadata and the file from the post? TIA
Pardon the almost blog post. I am posting this because while you can find partial answers in various places, I haven't run across a complete post anywhere, which would have saved me a ton of time. The problem is you need both sides to the story in order to verify either.
So I want to send a request using Postman to a Python/Flask web service. It has to have an image along with some metadata.
Here are the settings for Postman (URL, Headers):
And Body:
Now on to the web service. Here is a bare bones service which will take the request, print the metadata and save the file:
from flask import Flask, request
app = Flask(__name__)
# POST - just get the image and metadata
#app.route('/RequestImageWithMetadata', methods=['POST'])
def post():
request_data = request.form['some_text']
print(request_data)
imagefile = request.files.get('imagefile', '')
imagefile.save('D:/temp/test_image.jpg')
return "OK", 200
app.run(port=5000)
Enjoy!
Make sure `request.files['Image'] contains the image you are sending and follow http://flask.pocoo.org/docs/1.0/patterns/fileuploads/ to save the file to your file system. Something like
file = request.files['Image']
file.save('./test_image.jpg')
might do what you want, while you will have to work out the details of how the file should be named and where it should be placed.
I am using flask with python to develop my code for an Alexa skill which fetched Wikipedia data. I am also using Wikipedia library of Python.
Every time I try to test my skill Service simulator gives an error. Please help me find the error.
"There was an error calling the remote endpoint, which returned HTTP 404 : NOT FOUND"
from flask import Flask
from flask_ask import Ask, statement, question, session
import json
import requests
import time
import unidecode
import wikipedia
app = Flask(__name__)
ask = Ask(app,"/wiki_reader")
def get_wikisummary(searchitem):
summ=wikipedia.summary(searchitem,sentences=3)
sober=[unidecode.unidecode(summ)]
return sober
#app.route('/')
def homepage():
return "hi there, how ya doin?"
#ask.launch
def start_skill():
welcome_message='Hi, ask me about any country of the World'
return question(welcome_message)
#ask.intent("AnswerIntent")
def answer(ans):
summ1=get_wikisummary(ans)
summ2=[unidecode.unidecode(summ1)]
return statement("{}",format(summ2))
if __name__=='__main__':
app.run(debug=True)
I am using ngrok to host code which is currently hosted on localhost, on my machine.
I just figured out I was trying to run multiple codes on a single port. This is why it was giving not found error.
How do I make an authenticated request from a python script to appengine? I have found lots of different methods on the web but none work.
E.G. How do you access an authenticated Google App Engine service from a (non-web) python client? doesn't work, the request returns the login page.
That post is old, maybe something changed since then.
Has anyone got a nice wrapped object to do this?
Answered my own question:
from google.appengine.tools import appengine_rpc
use_production = True
if use_production:
base_url = 'myapp.appspot.com'
else:
base_url = 'localhost:8080'
def passwdFunc():
return ('user#gmail.com','password')
def main(argv):
rpcServer = appengine_rpc.HttpRpcServer(base_url,
passwdFunc,
None,
'myapp',
save_cookies=True,
secure=use_production)
# Makes the actual call, I guess is the same for POST and GET?
blah = rpcServer.Send('/some_path/')
print blah
if __name__ == '__main__':
main(sys.argv)
You can see one example of a non-web authenticated python client making requests in the Python client library used to process GAE Pull Queues at https://developers.google.com/appengine/docs/python/taskqueue/overview-pull#Using_the_Task_Queue_REST_API_with_the_Python_Google_API_Library