Import with multiple arguments: running python script in flask - python

I have a python script main.py that takes in two arguments (2 text files)
I'm using MAC OS X
Python 2.7
This runs easily on terminal with:
python main.py train.txt sample.txt
I have now developed a small front-end using Flask with very minor HTML as follows:
#front.py FLASK
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
#app.route('/')
def hello_world():
return render_template('index.html')
#app.route('/signup', methods = ['POST'])
def signup():
email = request.form['email']
email1 = request.form['email1']
# command below is just for testing, I wish to implement the same as this would if this would be typed in terminal.
print("main.py " + email + " " + email1)
return redirect('/')
if __name__ == "__main__":
app.run()
and the HTML
<!DOCTYPE html>
<html>
<head>
<title>T</title>
</head>
<body>
<form action="/signup" method="post">
<input type="text" name="email"></input>
<input type="text" name="email1"></input>
<input type="submit" value="Signup"></input>
</form>
</body>
</html>
This HTML code is simply using a form to take in the 2 arguments ( I find this easier than JS as I have no experience with that).
I have just written the
print("main.py " + email + " " + email1)
command above to test, it's not of any utility for now.
Usage of the parameters:
#main.py
from filter import Filter
import sys
# Get arguments from user
train = sys.argv[1]
messages = sys.argv[2]
# Open files for reading and writing
train_file = open(train, "rb")
messages_file = open(messages, "rb")
predictions_file = open("predictions.txt", "w")
# Create new filter and train it using the train-file
f = Filter()
f.train(train_file)
#filter the messages in messages_file, write results to predictions_file
f.filter(messages_file, predictions_file)
# Close all the files
train_file.close()
messages_file.close()
predictions_file.close()
I wish to now run my script which is main.py via this flask application itself, and want to know how this is possible.
I was using import main with another app decorator say /exec and manually changing the URL to go from 127.0.0.2000 to 127.0.0.2000/exec but this was giving errors as main requires the arguments to be passed.
Sorry if I'm unclear in explaining the problem, please let me know if I can explain anything in a better way to help understand the problem.
Thank you

You need to rework this script slightly. You should put all the code that deals with input inside a name == '__main__' block as you do in the Flask app, and the rest inside a function that you call from that block:
def do_stuff(train, messages):
# Open files for reading and writing
train_file = open(train, "rb")
...
predictions_file.close()
if __name__ == '__main__':
# Get arguments from user
train = sys.argv[1]
messages = sys.argv[2]
do_stuff(train, messages)
Now your Flask app can call main.do_stuff(email, email1).

Related

Building an HTML flask web page - input dependent on launch

I am building a website with flask on python. I am new to web development.
I built an HTML page, and now I need it's contents - number of buttons on the page for example - to be possibly different and automatic on each launch of app.py (the flask app running the website). Let's say that the number will be random between 1-10, a number generated in the app.py.
Does this mean that I need to change the HTML on every app.py launch, this by using python and editing the text file "index.html"? Is this bad practice and not a good way of achieving the goal? Are there other better methods to launch an input-dependent HTML page?
Thanks!
Code example:
def change_HTML_page(path,num):
# here read the text file in path, which is an HTML file, page description.
# inside in some place add more rows to describe buttons,
# as many as num.
# Add rows like this one <input type="button" id="i_bnutton" value="i" onclick="change_button_appearence(this)" />
# save text file afer the change
num_of_buttons = randint(0, 10)
page_path = r"docs/pages/index.html"
change_HTML_page(page_path, num_of_buttons);
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
Best way is to pass the num_of_buttons inside the html render command and constract all input buttons with a jinja loop inside your html.
Your code should look like below:
FLASK:
#app.route('/')
def index():
num_of_buttons = randint(0, 10)
return render_template('index.html', num_of_buttons=num_of_buttons)
if __name__ == '__main__':
app.run(debug=True)
And inside your HTML:
{% for i in range(0,num_of_buttons) %}
<input type="button" id="{{i}}_bnutton" value="{{i}}" onclick="change_button_appearence(this)" />
{% endfor %}

Get user input via for loop for python script in a Flask application

I am trying to create a very simple one-page Flask application for a python script that I have. The script requires multiple user inputs in a for-loop with the number of loops being user input as well.
Here is the code in my script to make it more clear:
def shared_books():
import requests as re
from bs4 import BeautifulSoup
import time
num_lists = int(input('Enter the number of lists you would like to search:'))
urls = []
page_counts = []
for i in range(num_lists):
urls.append(input(f'Enter the url for list {i + 1}:'))
page_counts.append(int(input(f'Enter the number of pages for list {i + 1}:')))
I want a simple HTML that will ask the user for the number of lists, then the URL and page count for each list as is shown in my function. Then it will run the entire function.
The HTML code I have right now is super simple and I don't want much else outside of the input parts:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
Please let me know how I can set up this application!
Firstly, I suggest you take a look at the Flask docs. You are doing it right in terms of having a view function, but the input() python keyword doesn't work like that in Flask. Instead, you should render an html template which you can then put your form input field into. Here is an example:
from flask import Flask, render_template
#flask initialising stuff, read docs for info
#app.route("/home")
def home():
return render_template("home.html")
Flask runs on your computer's local server "localhost", which is not publicly accessible. It conventionally runs on port 5000, which gives the name "localhost:5000".
When someone visits "localhost:5000/home", flask will look for a file called "home.html" in a pre-designated templates folder – the default is a directory called "templates" which you should put your html files into.
So if this is your "home.html" file:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
When you load the page associated with a specific function, it will return a template which is rendered as html. The above should look something like this:
And that is how to start.
Thank you for the answers! I haven't quite solved the previous issue but have approached it from a different angle which is working now! I will potentially post again if I don't solve it.
I am using flask forms to do what I was trying.

How do I receive an excel file as input using Flask and read it using openpyxl?

I've created a python script that loads an excel file up from my computer and, after working with the information inside it using openpyxl, saves a new excel file. The script works on my computer. For longevity purposes, I want to make the script into a website, using pythonanywhere or something similar to it (incorporating flask seemed like the best way to convert my script into a website). However, I am having trouble finding a way to accept a file from the user, as I have very little experience using flask. Here's the code I currently have that creates a "choose file" button and a "process file" button:
app = Flask(__name__)
app.config["DEBUG"] = True
#app.route("/", methods=["GET", "POST"])
def file_summer_page():
if request.method == ("POST"):
input_file = request.files["input_file"]
wb_master = load_workbook(input_file)
output_data = main(wb_master)
response = make_response(output_data)
response.headers["Content-Disposition"] = "attachment; filename=result.csv"
return response
return '''
<html>
<body>
<p>Load up the automated eval that MS Forms gives you:</p>
<form method="post" action="." enctype="multipart/form-data">
<p><input type="file" name="input_file" /></p>
<p><input type="submit" value="Process the file" /></p>
</form>
</body>
</html>
'''
Bear with me. Again, I haven't used Flask much, but this is my idea so far. Main(wb_master) essentially calls the script I made, so that it could hopefully run. At the moment, this returns the following error: "AttributeError: 'SpooledTemporaryFile' object has no attribute 'seekable'." In this case, I don't really know what it means, but I assume it is due to the fact that I am not reading the file correctly. Any help would be greatly appreciated!

Changing values using POST method in FLASK?

I'm new in StackOverflow and Python. I'm trying to make a basic application where I have my < form > tag, my flask app, and my .txt. I'm trying to change values but it's not working or I don't know why it's not working. Could any of you give me a hand?
Python Flask:
from flask import Flask,render_template,flash,request,redirect
import os
app = Flask(__name__)
from lines import get_line
#app.route('/', methods=['POST'])
def change_line():
search_line= "this"
try:
for line in this.input(os.path.join(APP_STATIC, u'line.txt'),inplace=1):
if search_line in line:
x = line.replace(search_line,search_line + "\n" + request.form.get(u'this'))
print (x)
else:
print (x)
except BaseException as e:
print e
return render_template('line.html')
#app.route('/')
def showLine():
line = get_line()
return render_template('line.html', line=line)
if __name__ == '__main__':
app.run()
HTML:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Change the value of this line</title>
</head>
<body>
<form method="post" name="test">
<h4>Chaging Values with POST Method</h4>
<div class="col-sm-9">
<label class="col-sm-3 col-sm-3 control-label">I want to change : </label>
<input type="text" class="form-control" name="address" value="{{ line }}">
</div>
<input type="submit" value="Save Changes!">
</form>
My .txt file:
I want to change this.
It's returning the value of "this".
Basically when I run my app it's displaying "this" when I try to edit for "Hello" it's returning me an error:
Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) Line
Found! : this.
127.0.0.1 - - [21/Oct/2016 13:09:07] "GET / HTTP/1.1" 200 - global name 'this' is not defined
127.0.0.1 - - [21/Oct/2016 13:09:30] "POST / HTTP/1.1" 200 -
My output:
Please click here to see my output
I'm sorry if this is a silly question, or if this was answered before, but I've been browsing for an answer for time and I have found nothing about this, I've tried different codes but not working, been watching youtube videos and everything.
If someone know the solution would be really helpful for me.
It's for learning and Python School. Thanks!
Working on Python 2.7
EDIT
I updated code with the suggestions below but it's not working yet.
it's not overwriting my "this" with replace.
from flask import Flask,render_template,flash,request,redirect
import os
app = Flask(__name__)
from lines import get_line
import fileinput
#app.route('/', methods=['POST'])
def change_line():
search_line= "this"
try:
for line in fileinput.input(os.path.join(APP_STATIC, u'line.txt'),inplace=1):
if search_line in line:
x = line.replace(search_line,search_line + "\n" + request.form.get(u'asd'))
print (x)
else:
print (x)
except BaseException as e:
print e
return render_template('line.html')
#app.route('/')
def showLine():
line = get_line()
return render_template('line.html', line=line)
if __name__ == '__main__':
app.run(debug=True)
this.input(os.path.join(APP_STATIC, u'line.txt'),inplace=1):
should be
fileinput.input(os.path.join(APP_STATIC, u'line.txt'),inplace=1):
(you will also need import fileinput)
you need to change this because this.input doesnt mean anyhthing to python ... it has no idea what this is ...
global name 'this' is not defined
as an aside you should really run with app.run(debug=True) while developing

Uploading CSV to Flask for background processing

I'm looking to use Flask to host a single-page website that would allow users to upload a CSV that would be parsed and put into a database. All of the database shenanigans are complete (through SQLalchemy in another Python script) and I've got everything worked out once a script has access to the CSV, I just need help getting it there.
Here's the scenario:
1. User directs browser at URL (probably something like
http://xxx.xxx.xxx.xxx/upload/)
2. User chooses CSV to upload
3. User presses upload
4. File is uploaded and processed, but user is sent to a thank you page while our
script is still working on the CSV (so that their disconnect doesn't cause the
script to abort).
It's totally cool if the CSV is left on the server (in fact, it's probably preferred since we'd have a backup in case processing went awry)
I think what I want is a daemon that listens on a socket, but I'm not really experienced with this and don't know where to start getting it configured or setting up Flask.
If you think some framework other than Flask would be easier, definitely let me know, I'm not tied to Flask, I've just read that it's pretty easy to set up!
Thank you very much!!
Here is a (very slightly simplified) example of handling file uploading in web.py based on a cook book example (the Flash example, which I have less experience with, looks even easier):
import web
urls = ('/', 'Upload')
class Upload:
def GET(self):
web.header("Content-Type","text/html; charset=utf-8")
return """
<form method="POST" enctype="multipart/form-data" action="">
<input type="file" name="myfile" />
<br/>
<input type="submit" />
"""
def POST(self):
x = web.input(myfile={})
filedir = '/uploads' # change this to the directory you want to store the file in.
if 'myfile' in x: # to check if the file-object is created
filepath=x.myfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
filename=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
fout = open(filedir +'/'+ filename,'wb') # creates the file where the uploaded file should be stored
fout.write(x.myfile.file.read()) # writes the uploaded file to the newly created file.
fout.close() # closes the file, upload complete.
raise web.seeother('/')
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
This renders a upload form, and then (on POST) reads the uploaded file and saves it to a designated path.

Categories