RuntimeError: Working outside of application context Error in Flask Server - python

I am trying to use the flask server, but since I faced an error, I started debugging it and by removing many codes to simplify the code and find finally reached to the following error::
Traceback (most recent call last):
File "C:\Code\SportsPersonClassifier\server\server.py", line 18, in <module>
print(classify_image())
File "C:\Code\SportsPersonClassifier\server\server.py", line 10, in classify_image
response = jsonify(util.classify_image(util.get_b64_for_virat()))
File "E:\Users\Acer\anaconda3\lib\site-packages\flask\json\__init__.py", line 358, in jsonify
if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug:
File "E:\Users\Acer\anaconda3\lib\site-packages\werkzeug\local.py", line 436, in __get__
obj = instance._get_current_object()
File "E:\Users\Acer\anaconda3\lib\site-packages\werkzeug\local.py", line 565, in _get_current_object
return self.__local() # type: ignore
File "E:\Users\Acer\anaconda3\lib\site-packages\flask\globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
This is my code:: in server.py
from flask import Flask, request, jsonify
import util
app = Flask(__name__)
#app.route('/classify_image', methods=['GET', 'POST'])
def classify_image():
response = jsonify(util.classify_image(util.get_b64_for_image()))
return response
if __name__ == "__main__":
print("Starting Python Flask Server For Sports Celebrity Image Classification")
util.load_saved_artifacts()
print(classify_image())
But the exact code works without any error, if I just remove jsonify() from the classify_image() function like this::
def classify_image():
response = util.classify_image(util.get_b64_for_image())
return response
If I write the classify_image function without jsonify it works as expected without error. I tried to solve the problem reading several StackOverflow answers but not working for my code. Please help me solve the problem with jsonify. Thank you.

As the error suggests, and as required by jsonify:
This requires an active request or application context
Calling the function this way via __main__ will not be within a Flask app context. Instead use app.run() to start the dev server, and then navigate to your route.

Related

Getting KeyError: 'Endpoint' error in Python when calling Custom Vision API

from azure.cognitiveservices.vision.customvision.prediction import CustomVisionPredictionClient
from msrest.authentication import CognitiveServicesCredentials
from azure.cognitiveservices.vision.customvision import prediction
from PIL import Image
endpoint = "https://southcentralus.api.cognitive.microsoft.com/"
project_id = "projectidhere"
prediction_key = "predictionkeyhere"
predict = CustomVisionPredictionClient(prediction_key, endpoint)
with open("c:/users/paul.barbin/pycharmprojects/hw3/TallowTest1.jpg", mode="rb") as image_data:
tallowresult = predict.detect_image(project_id, "test1", image_data)
Python 3.7, and I'm using Azure Custom Vision 3.1? (>azure.cognitiveservices.vision.customvision) (3.1.0)
Note that I've seen the same question on SO but no real solution. The posted answer on the other question says to use the REST API instead.
I believe the error is in the endpoint (as stated in the error), and I've tried a few variants - with the slash, without, using an environment variable, without, I've tried appending various strings to my endpoint but I keep getting the same message. Any help is appreciated.
Full error here:
Traceback (most recent call last):
File "GetError.py", line 15, in <module>
tallowresult = predict.detect_image(project_id, "test1", image_data)
File "C:\Users\paul.barbin\PycharmProjects\hw3\.venv\lib\site-packages\azure\cognitiveservices\vision\customvision\prediction\operations\_custom_vision_
prediction_client_operations.py", line 354, in detect_image
request = self._client.post(url, query_parameters, header_parameters, form_content=form_data_content)
File "C:\Users\paul.barbin\PycharmProjects\hw3\.venv\lib\site-packages\msrest\service_client.py", line 193, in post
request = self._request('POST', url, params, headers, content, form_content)
File "C:\Users\paul.barbin\PycharmProjects\hw3\.venv\lib\site-packages\msrest\service_client.py", line 108, in _request
request = ClientRequest(method, self.format_url(url))
File "C:\Users\paul.barbin\PycharmProjects\hw3\.venv\lib\site-packages\msrest\service_client.py", line 155, in format_url
base = self.config.base_url.format(**kwargs).rstrip('/')
KeyError: 'Endpoint'
CustomVisionPredictionClient takes two required, positional parameters: endpoint and credentials. Endpoint needs to be passed in before credentials, try swapping the order:
predict = CustomVisionPredictionClient(endpoint, prediction_key)

getting error 'function' object has no attribute 'as_view' while trying to run flask app

I started writing flask app after a long time more than a year, guess I have forgot something. This below code results in an error:
from flask import Flask
from flask import jsonify
from flask_restplus import Resource, Api
from home_iot.config import reader
from download_audio.ydla import download
app = Flask(__name__)
_api = Api(app, catch_all_404s=True, version=0.1,
title="REST HTTP API's Gateway",
descrition="REST API gateway")
api_ns = _api.namespace("iot", description="API.")
#api_ns.route("/tcpserver", methods=["GET"])
def advertise_tcpserver():
ip = reader.get_server_ip()
return jsonify({"tcpserver": ip})
if __name__ == "__main__":
app.run(host='127.0.0.1')
Error is:
$ python app.py
Traceback (most recent call last):
File "app.py", line 29, in <module>
#api_ns.route("/tcpserver", methods=["GET"])
File "/Users/ciasto/pyenvs/flaskrestplusiot/lib/python2.7/site-packages/flask_restplus/namespace.py", line 98, in wrapper
self.add_resource(cls, *urls, **kwargs)
File "/Users/ciasto/pyenvs/flaskrestplusiot/lib/python2.7/site-packages/flask_restplus/namespace.py", line 87, in add_resource
api.register_resource(self, resource, *ns_urls, **kwargs)
File "/Users/ciasto/pyenvs/flaskrestplusiot/lib/python2.7/site-packages/flask_restplus/api.py", line 264, in register_resource
self._register_view(self.app, resource, namespace, *urls, **kwargs)
File "/Users/ciasto/pyenvs/flaskrestplusiot/lib/python2.7/site-packages/flask_restplus/api.py", line 287, in _register_view
resource_func = self.output(resource.as_view(endpoint, self, *resource_class_args,
AttributeError: 'function' object has no attribute 'as_view'
Hope this can helps those who have this same error and have not found the solution
To complete the answer given by #v25 you must provide ressources to your namespace by inheriting from Ressource class in flask_restplus.
The following example works for me
Environment:
ubuntu 18.04
python 3.7.1
python requirements:
flask==1.1.2
flask-restplus==0.13.0
werkzeug==0.16.1
Source code:
iot.py
from flask_restplus import Namespace,Resource
api_ns = Namespace("iot", description="API.")
#api_ns.route("/tcpserver")
class AdvertiseTcpserver(Resource):
def get(self):
#TODO return the correct ip value
return {"tcpserver": "ip"}
app.py
from .iot import api_ns
from flask import Flask
from flask_restplus import Api
app = Flask(__name__)
_api = Api(app, catch_all_404s=True, version=0.1,
title="REST HTTP API's Gateway",
descrition="REST API gateway")
_api.add_namespace(api_ns, path='/some/prefix')
app.run()
Test command:
#!/bin/sh
wget localhost:5000/some/prefix/tcpserver
Please let me know if this helped.
Don't think that's the correct way to define the namespace with flask_restplus. Have a look at scaling docs.
You're probably looking for something like:
iot.py
from flask_restplus import Namespace
api_ns = Namespace("iot", description="API.")
#api_ns.route("/tcpserver", methods=["GET"])
def advertise_tcpserver():
ip = reader.get_server_ip()
return jsonify({"tcpserver": ip})
Then in your main app.py:
# other imports
from .iot import api_ns
app = Flask(__name__)
_api = Api(app, catch_all_404s=True, version=0.1,
title="REST HTTP API's Gateway",
descrition="REST API gateway")
_api.add_namespace(api_ns, path='/some/prefix')
Also you appear to be using Python 2.7 which has been discontinued. I'd suggest upgrading to the latest version, using either a virutal environment or docker so as not to mess with your system's python.

Flask cache set method throwing KeyError?

In order to cache some data, I am calling cache.set method. However it is throwing KeyError. The error log:
File "D:\Sample_Project\SomeRouter.py", line 176, in run
FetchFeed._prepareCache(f_content, cache, _program, _sprint)
File "D:\Sample_Project\SomeRouter.py", line 197, in _prepareCache
cache.set(cKey, data[last_index:last_index + MAX_DATA_PER_PAGE])
File "c:\python\lib\site-packages\flask_caching\__init__.py", line 254, in set
return self.cache.set(*args, **kwargs)
File "c:\python\lib\site-packages\flask_caching\__init__.py", line 246, in cache
return app.extensions["cache"][self]
KeyError: <flask_caching.Cache object at 0x04F9C8D0>
The server module looks like :
cache_type = 'simple' if 'FLASK_ENV' in os.environ and os.environ['FLASK_ENV'] == 'development' else 'uwsgi'
cache = Cache(config={'CACHE_TYPE': cache_type})
app = Flask("MY_PROJECT")
cache.init_app(app)
# some api.route functions
# goes here ....
if __name__ == "__main__":
with app.app_context():
cache.clear()
app.run(host="0.0.0.0")
And SomeRouter module:
from server import cache
#staticmethod
def _prepareCache(data, cache, program):
total_records = len(data)
if total_records > 0:
cKey = FetchFeed \
._constructCacheKey(program)
cache.set(cKey, data)
else:
print("data size is empty.")
Note: I have removed unnecessary codes.
I also put breakpoints, and called cache.set(some_key, some_value) in server module itself. It is returning True, but same cache object is throwing KeyError when imported and used in SomeRouter module. Can it be that the way I am importing an object is wrong? I also tried importing the cache object right before using it, but it did not work. Any idea what is going on here?
The problem was I was accessing cache object outside request context i.e. in "SomeRouter" module, and because of which it was unaware that under which context it is been used.
In server module where request has been received, the cache knows about the app application, but during cache.set(cKey, data) in SomeRouter module, it throws KeyError. This error is justified as mentioned above.
The resolution is to push the application context as below:
from server import app, cache
# Using context
with app.app_context():
cache.set(cKey, data)
This will push a new application context (using the application of app).
All thanks to Mark Hildreth, for his great answer on context in flask

Blueprints in Flask "Attribute 'function' object has no attribute 'name'

Problem Description
Getting error message when trying to start Flask.
Traceback (most recent call last):
File "./run.py", line 3, in <module>
from app import app
File "/home/xxxxxx/xxxx.xxxxxxx.com/ClientTracker/app/__init__.py", line 13, in <module>
app.register_blueprint(admin)
File "/home/xxxxx/xxxxx.xxxxxxx.com/ClientTracker/env/local/lib/python2.7/site-packages/flask/app.py", line 65, in wrapper_func
return f(self, *args, **kwargs)
File "/home/xxxxx/xxxxx.xxxxxxx.com/ClientTracker/env/local/lib/python2.7/site-packages/flask/app.py", line 958, in register_blueprint
if blueprint.name in self.blueprints:
AttributeError: 'function' object has no attribute 'name'
This is a migration from a simpler hierarchy implementing Blueprints. I'm splitting out the function of the frontend and the admin panel.
I built this step by step and had both sides working fine.
Started migrating (functions and routes). After moving some code, I started getting an error message (basically the same as above, but different line).
Troubleshooting
Searched through related posts on stackO
Initially it was complaining about the second route statement I had. I
started removing code (rolling back) to what I (thought was) a known
good state. However I continued to have issues.
I have it down to the minimum code I believe I need but still getting
errors.
If I remove the registration in the init.py file, the frontend works
perfectly.
Code
#ClientTracker/run.py
#!env/bin/python
from app import app
app.run(host='0.0.0.0', port=8080, debug=False)
#ClientTracker/app/__init__.py
# Import flask and template operators
from flask import Flask, render_template
# Define the WSGI application object
app = Flask(__name__)
# Import a module / component using its blueprint handler variable (mod_auth)
#from app.mod_auth.controllers import mod_auth as auth_module
from app.admin.views import admin
from app.client.views import client
# Register blueprint(s)
app.register_blueprint(admin)
app.register_blueprint(client)
#ClientTracker/app/admin/views.py
from flask import render_template, request, Blueprint
from app import app
import MySQLdb
import datetime
admin = Blueprint(
'admin',
__name__,
url_prefix='/admin',
template_folder='templates',
static_folder='static'
)
#admin.route('/')
def admin():
return "ok"
I'm out of ideas.
Ok, so as seems to happen, I spend an hour looking, another 15 mins composing a question and then after I hit post, I find the answer.
I found a post (https://github.com/pallets/flask/issues/1327) that had the answer.
Basically, you cannot have a function name with the same name as your Blueprint name. Seems obvious now, but certainly stumped me for a while.
In thinking about it, my original "working" state had a dummy function name serving the '/'. When I rolled back, I didn't roll back far enough.
Replaced def admin(): with def admin1(): (will fix this better in prod) and all worked.
I hope this post helps someone else. Please still feel free to comment. As always, the group is always smarter than the individual. Lastly, thanks for reading this far. :-)
Your blueprint name is same with your function name, try to rename the function name instead.
Note that the blue print name and the function name can not be the same.
Make use if this tutorial to learn more about Blueprints, https://realpython.com/flask-blueprint/

Unit testing bottle py application that uses request body results in KeyError: 'wsgi.input'

When unit testing a bottle py route function:
from bottle import request, run, post
#post("/blah/<boo>")
def blah(boo):
body = request.body.readline()
return "body is %s" % body
blah("booooo!")
The following exception is raised:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in blah
File "bottle.py", line 1197, in body
self._body.seek(0)
File "bottle.py", line 166, in __get__
if key not in storage: storage[key] = self.getter(obj)
File "bottle.py", line 1164, in _body
read_func = self.environ['wsgi.input'].read
KeyError: 'wsgi.input'
The code will work if running as a server via bottle's run function, it's purely when I call it as a normal Python function e.g. in a unit test.
What am I missing? How can I invoke this as a normal python func inside a unit test?
I eventually worked out what the problem is. I needed to "fake" the request environment for bottle to play nicely:
from bottle import request, run, post, tob
from io import BytesIO
body = "abc"
request.environ['CONTENT_LENGTH'] = str(len(tob(body)))
request.environ['wsgi.input'] = BytesIO()
request.environ['wsgi.input'].write(tob(body))
request.environ['wsgi.input'].seek(0)
# Now call your route function and assert
Another issue is that Bottle uses thread locals and reads the BytesIO object you put into request.environ the first time you access the body property on request. Therefore if you run multiple tests with post data, e.g. in a TestCase, when you come to read it in your request callback it will only return the value it was initially given, not your updated value.
The solution is to scrub all the values stored on the request object before each test, so in your setUp(self) you can do something like this:
class MyTestCase(TestCase):
def setUp():
# Flush any cached values
request.bind({})
Check out https://pypi.python.org/pypi/boddle. In your test you could do:
from bottle import request, run, post
from boddle import boddle
#post("/blah/<boo>")
def blah(boo):
body = request.body.readline()
return "body is %s" % body
with boddle(body='woot'):
print blah("booooo!")
Which would print body is woot.
Disclaimer: I authored. (Wrote it for work.)

Categories