0

I created a python REST web-service, and it will execute a series of subprocess commands to restart another python REST webservice. But the problem is it doesn't really start my other REST service after I call it.

Here is my code for the REST API :

from flask import Flask, jsonify, request, make_response
from flask_restful import fields, reqparse, abort, Api, Resource
import sqlalchemy
from sqlalchemy.sql import table, column, select, update, insert, delete, func
from sqlalchemy.orm import sessionmaker
import requests
import time
import traceback
import subprocess
import os

app = Flask(__name__)
api = Api(app)

class RestartPython(Resource):
    def get(self):

        command1 = 'fuser -k 9876/tcp'
        proc1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
        proc1.wait()

        print('kill python process done')

        command2 = 'source activate envpy3'
        proc2 = subprocess.Popen(command2, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
        proc2.wait()

        print('switch python env done')

        command3 = 'python ReceiveCall.py'
        print(command3)
        proc3 = subprocess.Popen(command3, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
        proc3.wait()

        print('ReceiveCall started')

        return make_response(jsonify({'message': 'Python webservice is restarted', 'status': 'Ok'}), 200)

    api.add_resource(RestartPython, '/restart')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8082, debug=True)

This will works if I just run it without wrapping them in web-service

import subprocess

if __name__ == '__main__':
    command1 = 'fuser -k 9876/tcp'
    proc1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
    proc1.wait()

    print('kill python process done')

    command2 = 'source activate envpy3'
    proc2 = subprocess.Popen(command2, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
    proc2.wait()

    print('switch python env done')

    command3 = 'python ReceiveCall.py'
    print(command3)
    proc3 = subprocess.Popen(command3, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
    proc3.wait()

    print('ReceiveCall started')

Any ideas?

Abc123
  • 35
  • 9
  • what are the output,error you are getting after running each Popen instance , use below link to get the output and error https://stackoverflow.com/questions/1996518/retrieving-the-output-of-subprocess-call – pankaj mishra Dec 06 '17 at 09:42
  • if my answer solves your issue, can you accept it? a right tick mark below down vote button – pankaj mishra Dec 06 '17 at 09:55

1 Answers1

1

instead of wait() i would recommend to use communicate() . communicate is used to avoid deadlock wherever pipe is used . Let me know if below modification works for you

from flask import Flask, jsonify, request, make_response
from flask_restful import fields, reqparse, abort, Api, Resource
import sqlalchemy
from sqlalchemy.sql import table, column, select, update, insert, delete, func
from sqlalchemy.orm import sessionmaker
import requests
import time
import traceback
import subprocess
from subprocess import PIPE,Popen
import os

app = Flask(__name__)
api = Api(app)

class RestartPython(Resource):
    def get(self):

        command1 = 'fuser -k 9876/tcp'
        proc1 = subprocess.Popen(command1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        #proc1.wait()
        (stdout, stderr) = proc1.communicate()

        print '.'.join(stdout)
        print '.'.join(stderr)

        print('kill python process done')

        command2 = 'source activate envpy3'
        proc2 = subprocess.Popen(command2, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
        #proc2.wait()
        proc2.communicate()

        print('switch python env done')

        command3 = 'python ReceiveCall.py'
        print(command3)
        proc3 = subprocess.Popen(command3, stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, shell=True)
        #proc3.wait()
         proc3.communicate()

        print('ReceiveCall started')

        return make_response(jsonify({'message': 'Python webservice is restarted', 'status': 'Ok'}), 200)

    api.add_resource(RestartPython, '/restart')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8082, debug=True)
pankaj mishra
  • 2,555
  • 2
  • 17
  • 31
  • what is the problem you are facing and expected output? – pankaj mishra Dec 06 '17 at 10:12
  • I expect my other REST API will be started after I run it, "ReceiveCall.py" is my another python REST API. – Abc123 Dec 06 '17 at 10:16
  • And if I run those subprocess commands without calling it as a web-service, it will works. – Abc123 Dec 06 '17 at 10:18
  • did not get your last comment "...calling as a web-service" – pankaj mishra Dec 06 '17 at 10:21
  • run the code as it is , i have made some modification, just wanted to check even the subprocess Popen is called or not – pankaj mishra Dec 06 '17 at 10:34
  • I got this b'' for those 2 print functions – Abc123 Dec 06 '17 at 11:00
  • just a small doubt, since i m not very much familiar with flask !! are you even calling get() anywhere in flask ? – pankaj mishra Dec 06 '17 at 11:07
  • yeah, I did call it from a browser as GET – Abc123 Dec 06 '17 at 11:20
  • may be you wanted to have a look on url https://techarena51.com/blog/how-to-install-python-3-and-flask-on-linux/ also is there any specific reason to create a class? most of the example i have seen using functions only – pankaj mishra Dec 06 '17 at 11:31
  • my approach for this is because I need to install the main python web-service into many servers, and with a web-service that can handle restart python command, I can call them as a batch and restart all the web-service at once with a loop. :D – Abc123 Dec 06 '17 at 15:26