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

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.

Related

RuntimeError: Working outside of application context Error in Flask Server

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.

AttributeError: 'str' object has no attribute 'copy' in flask & celery

I am having a huge data set in elasticsearch which I need to export in csv as per the end user's request. End user will send a query which would filter out my elasticsearch data & generate the results. Since the csv files are big and there are much more processing time I want to run this process in background.
To implement this I created a flask app & integrated the celery module. My celery process accepts the request parameters & start the background processing of csv.
Below is my code -
from flask import Flask, request, jsonify
from task import make_celery
import json, sys, time, pandas, boto3
from elasticsearch import Elasticsearch
from elasticsearch.helpers import scan
app = Flask(__name__)
app.config.update(
CELERY_BROKER_URL='sqs://AKIARYGF4GTjnjkKJXHHR:EkLmCgD3Ch+0AqLe+cdlTwnknkXwVMbkSAG4Jm#',
)
celery = make_celery(app)
#app.route("/export", methods=['POST','GET'])
def process():
exportList.delay(index=request.args['index'], query=request.args['query'] , export_id=request.args['export_id'])
return 'I sent async request!'
#celery.task(name='example.exportList')
def exportList(index, query, export_id):
start_time = time.time()
print("\ncreating client instance of Elasticsearch")
elastic_client = Elasticsearch(['xyz-test-5q76b4fabvhjjbhjbjbjb2bt6xrhhsi.ap-south-1.es.amazonaws.com'],
http_auth=('test', '854852#123$%'),
scheme="https",
port=443,
)
scan_docs = pandas.DataFrame()
for hit in scan(elastic_client, index=index, query=query):
scan_source_data = hit["_source"]
scan_id = hit["_id"]
scan_doc_data = pandas.Series(scan_source_data, name=scan_id)
scan_docs = scan_docs.append(scan_doc_data)
scan_docs.to_csv("/tmp/scandocs.csv", ",")
"""
Further intimating the user that the file is ready via email
"""
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
I am getting an error in my celery console
[2021-08-17 07:24:15,229: ERROR/ForkPoolWorker-2] Task example.exportList[1d30ab46-f4de-408a-8add-e3b98d633bef] raised unexpected: AttributeError("'str' objec
t has no attribute 'copy'")
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.8/site-packages/celery/app/trace.py", line 450, in trace_task
R = retval = fun(*args, **kwargs)
File "/home/ubuntu/celery/task.py", line 14, in __call__
return self.run(*args, **kwargs)
File "/home/ubuntu/celery/example.py", line 47, in exportList
for hit in scan(elastic_client, index=index, query=query):
File "/home/ubuntu/.local/lib/python3.8/site-packages/elasticsearch/helpers/actions.py", line 550, in scan
query = query.copy() if query else {}
AttributeError: 'str' object has no attribute 'copy'

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/

Cannot use jinja2 PackageLoader on Google App Engine

I'm trying to use the PackageLoader jinja2 provides but I cannot get it to work.
In my app.yaml I have the required libraries declared:
libraries:
- name: jinja2
version: latest
- name: setuptools
version: latest
The smallest example I could create:
import webapp2, sys
from jinja2 import Environment, PackageLoader
sys.path += ['lib/somepackage']
class Test(webapp2.RequestHandler):
def get(self):
env = Environment(loader=PackageLoader('common'))
self.response.write(env.get_template('test.html').render())
routes = [(r"/", Test)]
app = webapp2.WSGIApplication(routes, debug=True)
The package common exists in the directory lib/somepackage and has a package templates which contains a file test.html. The html file only contains the text 'test'.
When the PackageLoader is constructed it's provider is always a NullProvider when in Google App Engine. When I manually request a provider I get a DefaultProvider so obviously something is wrong here.
To request a provider I ensure lib/somepackage is in the sys.path by going to that dir, then:
>>> import pkg_resources
>>> provider = pkg_resources.get_provider('common')
>>> provider
<pkg_resources.DefaultProvider instance at 0x8490b2c>
When this fails in Google App Engine, this is the relevant part of the traceback:
File "/<>/test/main.py", line 7, in get
self.response.write(env.get_template('test.html').render())
File "/<>/google_appengine/lib/jinja2-2.6/jinja2/environment.py", line 719, in get_template
return self._load_template(name, self.make_globals(globals))
File "/<>/google_appengine/lib/jinja2-2.6/jinja2/environment.py", line 693, in _load_template
template = self.loader.load(self, name, globals)
File "/<>/google_appengine/lib/jinja2-2.6/jinja2/loaders.py", line 115, in load
source, filename, uptodate = self.get_source(environment, name)
File "/<>/google_appengine/lib/jinja2-2.6/jinja2/loaders.py", line 226, in get_source
if not self.provider.has_resource(p):
File "/<>/google_appengine/lib/setuptools-0.6c11/pkg_resources.py", line 1170, in has_resource
return self._has(self._fn(self.module_path, resource_name))
File "/<>/google_appengine/lib/setuptools-0.6c11/pkg_resources.py", line 1218, in _has
"Can't perform this operation for unregistered loader type"
NotImplementedError: Can't perform this operation for unregistered loader type
When I use a FileSystemLoader instead it works, however this won't work in a zip I guess:
import common.templates
env = Environment(loader=FileSystemLoader(common.templates.__path__))
I have seen this SO question but this isn't the problem.
Update:
I just tested the example in the 1.7.6 SDK and this works, however I'd love to see this working on a older SDK (or the old_dev_appserver).
The problem, I think, was with pkg_resources.
Some of the os related functionality isn't implemented in GAE but either jinja2 or Google provided a workaround it seems.
These links illustrate the issue:
http://code.google.com/p/googleappengine/issues/detail?id=60
https://github.com/mitsuhiko/jinja2/issues/143
Jinja2 PackageLoader on google app engine
https://bitbucket.org/tarek/distribute/issue/73/pkg_resources-fails-on-google-app-engine
I've used
jinja_environment = jinja2.Environment(autoescape=True,
loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
as boilerplate to get the templates from the "template" directory in the same directory as the file that is setting the definition. But the question is about files zipped as eggs and using PackageLoader
Is there an __init__.py file inside the package? You said it worked on 1.7.6, though.

AttributeError for SUDS in GAE

I am trying to include the SUDS library in a Python project through Google App Engine.
My code tries the following:
from suds.client import Client
from suds.wsse import *
And, once I've deployed on GAE, I encounter the following error:
File ".../myfile.py", line 13, in <module>
from suds.client import Client
File ".../suds/__init__.py", line 154, in <module>
import client
File ".../suds/client.py", line 25, in <module>
import suds.metrics as metrics
AttributeError: 'module' object has no attribute 'suds'
I've been looking around for a little while, and it seems like SUDS is workable with GAE. I added the fixes outlined here, but that doesn't seem to be the problem. It seems like App Engine doesn't even get to that point.
Any info or suggestions?
I'm using Python 2.7 and SUDS 0.4.
Have you tried doing a simple import suds.client? Also make sure you include the suds folder in your application as App Engine doesn't include it by default. I hope that helps.

Categories