-1

I am using flask framework. The web page accepts few inputs like the file and and file name and when they click on submit, I ll basically run a shell script by passing those arguments. Currently, I am using subprocess to call the script which would run a docker container. I have no problem when I make one request at a time. The issue is when I make concurrent requests to server. Only one request is fulfilled and other request fails. Only when the script has successfully run I would redirect to other page where the use would be able to download the output file.

I am a newbie to flask and python, I appreciate your help. Thanks in Advance

    def run_script(file_name,available_port):
        print("Running the shell script")
        script_output =  subprocess.call(['./runDockerFlow.sh',file_name,available_port],cwd="/home/ubuntu-testing/Desktop/DockerWeb/")
        print(script_output.stdout)

    
    @app.route('/upload',methods=['POST','GET'])
    def on_click_upload():
        if request.method == 'POST':
            f=request.files['file']
            fname=request.form.get("FName")
            f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename)))
            if available_port != 0:             
                run_script(f.filename,str(available_port))
        return render_template("download.html",k=k)

    
    @app.route('/download',methods=['GET','POST'])
    def download():
        return send_file("container_"+user_info.username+"/output_files.zip",as_attachment=True)

By the way I have configured the upload folder only adding necessary code for your reference.

David Maze
  • 130,717
  • 29
  • 175
  • 215
Aj_Crux
  • 1
  • 1

1 Answers1

-1

As said by another user on this forum: subprocess.call() returns the exit code, not the stdout. You can use the Popen class directly!

subprocess.Popen([.....],stdout=subprocess.PIPE).communicate()[0]

Here we tell .communicate to grab the output in a form of a tuple (stdout, stderr), so we then we take the stdout using the [0]

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • I made the change you asked for but I get this error when I try to make a concurrent request, print(script_output.stdout) AttributeError: 'bytes' object has no attribute 'stdout' – Aj_Crux Mar 04 '22 at 08:47
  • No, don't run `Popen` if you can avoid it. Instead, replace `subprocess.call` with `subprocess.check_output` (which will return the output directly as a string) or perhaps `subprocess.run` (which provides a `CompletedProcess` object which has a `.stdout` attribute like your original code expects). – tripleee Mar 04 '22 at 12:29
  • @tripleee why would one avoid Popen? `.call` directly uses Popen doesn't it? While `check_output` just produces `process = Popen(stdout=PIPE, *popenargs, **kwargs)` `output, err = process.communicate()`. I don't see a difference between using Popen and check_output except check_output catching non-0 errors. A sanity check could easily solve that. Is there any actual advantage of using `check_output` over directly using `Popen`? I use all of them interchangeably, and would appreciate any guidance! – Artur Zaytsev Mar 05 '22 at 11:15
  • Like the documentation tells you, `Popen` requires you to manage the process object for its entire lifetime (communicate, wait, kill) whereas the higher-level functions encapsulate all the required plumbing into essentially a one-liner. If you need e.g. background processes etc, the only solution is `Popen`, but for simple use cases, you can and should avoid the multiple lines of boilerplate code. – tripleee Mar 05 '22 at 17:06