I just started working with web tools and flask.I have a python script with 9 functions and I am trying to make a flask application. the main view of this application would do the same thing as my python script (in which some functions are intermediate meaning they do not produce the final output and 2 functions produce the final output). since for one route I have 9 functions, what do you suggest? shall I rename my original script as view.py and call it in the app.py (under the corresponding route) or there is better way?
Creating a separate file is always a better choice. It will make the code more readable and understandable.
Simply create a file and call the method in app.py like this.
from flask import Flask, jsonify
from views import your_method_name
# Initialize the app
app = Flask(__name__)
# Route (e.g. http://127.0.0.1:5000/my-url)
#app.route("/my-url", methods=['POST'])
def parse():
response = your_method_name() # call the method
return jsonify(response)
if __name__ == '__main__':
app.run()
Related
I'm using apidoc to generate a documentation website. On running, it creates a folder called doc, which contains an index.html file and accompanying css and js.
I'd like to be able to serve this folder with a Flask server, but can't work out how to do it.
My folder structure looks like this
-root
--- doc/ #contains all of the static stuff
--- server.py
I've tried this, but can't get it to work:
app = Flask(__name__, static_url_path="/doc")
#app.route('/')
def root():
return app.send_from_directory('index.html')
One of the problems is that all of the static files referenced in the index.html generated by apidoc are relative to that page, so /js/etc. doesn't work, since it's actually /doc/js...
It would be great if someone could help me with the syntax here. Thanks.
I spot three problems in code.
a) you do not need to use static_url_path, as send_from_directory is independent of it
b) when I try to run above code, and go to /, I get a AttributeError: 'Flask' object has no attribute 'send_from_directory' - this means translates to app.send_from_directory is wrong - you need to import this function from flask, ie from flask import send_from_directory
c) when I then try to run your code, I get a TypeError: send_from_directory() missing 1 required positional argument: 'filename', which means send_from_directory needs another argument; it needs both a directory and a file
Putting this all together you get something like this:
from flask import Flask
from flask import send_from_directory
app = Flask(__name__)
#app.route("/")
def index():
return send_from_directory("doc", "index.html")
As a takeway (for myself):
reading the documentation helps a lot ( https://flask.palletsprojects.com/en/1.1.x/api/ )
having a close look at the - at first scary - error messages gives really good hints on what to do
I have an Azure Web app stacked on python and running a flask app to call a function and this function returns a list of country name which I have saved in pickle file. Lets say I have a total of 100 countries so whenever I run the app it reads 100 countries from that pickle file but sometimes it's stuck to 98 or 99 countries so not sure where I am loosing 1 or 2 countries from that list. This issue only happens on azure web app otherwise it retrieves full 100 countries. Below is the code I'm using to load the pickle file having country list of 100:
import pickle
path=os.getcwd()+'\\'
def example():
country_list=pickle.load(open(path+"support_file/country_list.p","rb"))
print(len(country_list))
return country_list
Here is my flask app.py to call the function:
from other_file import example
from flask import Flask, request
app = Flask(__name__)
#app.route("/", methods=["POST", "GET"])
def query():
if request.method == "POST":
return example()
else:
return "Hello!"
if __name__ == "__main__":
app.run()
The above list is then used in a function and my output depends on all the elements of this list but if an element or two goes missing while loading this pickle then my output changes. So I'm not missing out this elements consistently but it happens for say 1 in every 20 times, so is this a problem of Azure Web app or is something wrong with my pickle? I tried to recreate the pickle but same problem keeps on coming up once in a while.
It seems pickle load reads till it's buffer is full. So, you would have to iterate like below, until it gets an EOF exception. Unfortunately, I could not find a graceful way to run the loop without catching exception. You might also need to cache the list instead of unpickling on every request to optimize performance.
with open(os.getcwd()+'/support_file/country_list.p','rb') as f:
country_list = []
while True:
try:
country_list.append(pickle.load(f))
except EOFError:
break
I want to send data to html in flask framework, i have a function which receives dictionary as a parameter, then there are several functions applied on dictionary. after that final result i want to render in to html page. Its been 48 hours i am trying from different blogs but didn't get precise solution.
imports ...
from other file import other_functions
from other file import other_functions_2
from other file import other_functions_3
app = Flask(__name__, template_folder='templates/')
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
calculate_gap = other_functions(input)
calculate_matrix = other_functions_2(input)
average = other_functions_3(input)
data = dict{'calculate_gap':calculate_gap, 'calculate_matrix':calculate_matrix,'average':average}
return render_template('pages/dashboard.html', data = data)
if __name__ == "__main__":
app.run(debug=True)
TRACEBACK
Methods that Flask can route to don't take dictionaries as inputs, and the arguments they do take need to be matches by a pattern in the route. (See https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations)
You'd get the same error if you changed
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
to
#app.route("/dashboard")
def calculate_full_eva_web(input):
Your path forward depends on how you want to pass data when you make the request. You can pass key/value pairs via URL parameters and retrieve them via the request.args object. That might be close enough to what you want. (You'll need to remove the argument declaration from calculate_full_eva_web())
Something like
from flask import request
#app.route('/dashboard')
def calculate_full_eva_web():
input = request.args
...
I'm working on some code that pulls course info from Canvas. As pure python, it works fine. If I try to incorporate it with Flask, I get the following error
requests.exceptions.MissingSchema: Invalid URL 'run/api/v1/courses/1234567': No schema supplied. Perhaps you meant http://run/api/v1/courses/1234567?
This is the code in question:
Canvas file
import sys
from canvasapi import Canvas
def getinfo():
canvasurl = "https://canvas.instructure.com/";
canvastoken = #Redacted for this example
try:
canvastoken = sys.argv[1];
canvasurl = sys.argv[2];
except:
print()
#Create a new canvas object passing in the newly aquired url and token
canvas = Canvas(canvasurl, canvastoken);
#print(canv)
# Create a new course oject -- passing in course number as a parameter
# Course number is currently hard coded
print(canvas.get_course(1234567))
Flask file code (the file that I'm trying to run):
from flask import Flask
import canvas
canvas.getinfo()
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
No schema provided usually means you haven't specified the http:// or https:// in the URL.
In the code you provided, I don't see any reference to a run/api/v1/courses/1234567. One possibility is if you are using the url_for method from requests anywhere in your code, try setting _external=True:
url = url_for('relativeURL', _external=True)
This allows Flask to construct an absolute URL (i.e., a URL with domain included).
If you aren't using url_for, check other places in your code where you might be omitting the http or https from the URL.
If you update your question to include the part that refers to the offending URL, we might be able to provide more specific help.
I am not really familiar with Python and am trying to transform one of my php webapps to python. Currently I am running the app on localhost using the appengine launcher and this is what I am trying to do.
I am trying to get a list of all the parameters posted to the url and then submit them to a page and get its content.
So basically:
1: get the params
2: get contents of a url by submitting those params (the PHP equivalent of curl of file_get_contents)
This is my code so far
from google.appengine.ext import webapp
class MyHandler(webapp.RequestHandler):
def get(self):
name1 = self.request.get_all("q")
name2 = self.request.get_all("input")
return name1,name2
x = MyHandler()
print x.get()
and the url
http://localhost:8080/?q=test1&input=test2
and this is the error I get
AttributeError: 'MyHandler' object has no attribute 'request'
Now I cant get it to print anything and I am not sure how I can get the contents of another url by submitting name1 and name2
I have tried looking at the documentation but I cant make sense of it since all they have is just 2 lines of code to get the use of function started.
x = MyHandler()
print x.get()
This is not a typical part of an AppEngine app. You don't use print to return output to the browser.
When you create a new app in AppEngineLauncher it gives you a skeleton project that looks like this:
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello world!')
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
Your app has to be run similarly. You need a main() method that creates a wsgi_app which is in charge of calling your handler. That main() function is called by dev_appserver, assuming your app.yaml file is set up correctly.
def get(self):
name1 = self.request.get_all("q")
name2 = self.request.get_all("input")
self.response.out.write(name1 + ',' + name2)
Should work if you've set up your app correctly.
You will need a few more lines of code to make this work if you are going to use the WebApp framework. Stick the following lines at the end of your code (and get rid of the last two lines where you instantiate your class and call the get method)
application = webapp.WSGIApplication([('/', MyHandler)])
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()