'Running flask as a subprocess in order to start a tkinter window

I have an application, working with python 3.7 and flask, that runs locally. I'd like to ask the user (myself) to give a path to a folder. I know how to use tkinter when running only python, I know how to send the data from flask to the python script and so on, but I cant find a way to run tkinter in this context.

I know that tkinter is supposed to run in the main thread, and I've tried working with subprocess in order to have tkinter window as the main thread, and flask as a subprocess.

Currently, I'm launching my script main.py, who launch flask as a subprocess with subprocess.Popen(). But even then, since the tkinter window is open from a flask route, it is obviously not the main thread. My main thread is a Loop waiting for a user input to exit the script and kill flask.exe ...

@app.route('/getPath', methods=['GET', 'POST'])
def getPath():
    prompter = promptlib.Files()
    myPath = prompter.dir()
    return render_template('form.html', data={'path': myPath})

Is there a way to achieve something like this ? Even by replacing the tkinter window by another module, JavaScript or anything allowing the user to browse the windows explorer to select the path.



Solution 1:[1]

As @aaron said, you want <input type="file">. However, in order to do this, you need to have server side code to handle this data. Flask-WTForms helps with this. Basically, in your code, you first make a class:

from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
class UploadFileClass(FlaskForm): # Create a class based on the FlaskForm base we imported earlier
    file = FileField("Select a file", validators=[FileRequired()]) # Now we create a file field. 
    # The first argument is the label, and the second one is any validators you may want
    # For more info on validators, see https://flask-wtf.readthedocs.io/en/1.0.x/form/#validation

And now, in your route, allow POST requests:

@app.route("/upload", methods=["GET", "POST"])
def route():
    ...

Next, import your form (at the top of the file preferably) and add code to handle your file in the route:

# ... in your route ...
form = UploadFileClass() # Make a new instance of the class

if form.validate_on_submit(): # If the form was successfully sent
    data = form.file.data # Get the data
    data.save("wherever") # Save the data

Refer to the Creating Forms section of the docs for more information on creating a form.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zurgeg