2

I've developed a classifier for test classification. and trying to access it using REST API. Here is the code:

clf_model = joblib.load('MNB_Clf.pkl','r')

app = Flask(__name__)

@app.route('/spend_api',methods=['POST'])
def make_predict():
    data = request.get_json(force=True)

    test_data = pd.read_csv(data)

    pred_proba_class = clf_model.predict_proba(test_data['ColumnName1'])


    final_pred_file = pd.DataFrame(pred_proba_class)

    sub_file = 'output_'+str(datetime.datetime.now().strftime("%Y-%m-%d-%H-%M")) + '.csv'
    return jsonify(results=final_pred_file.to_csv(sub_file))
if __name__ == '__main__':
  app.run(port = 9000,debug=True)

I am trying to send the CSV file to the api using the below code:

url = 'http://localhost:9000/spend_api'
files = {'file': ('Test_data_final.csv')}
r = request.post(url,files=files)

I am getting a Runtime Error. Could you please help how to resolve the issue.

Here is the error:

  RuntimeError                              Traceback (most recent call 
  last)
  <ipython-input-15-4b8522aa1eb0> in <module>()
         3 url = 'http://localhost:9000/spend_api'
         4 files = {'file': ('Test_data_final.csv')}
   ----> 5 r = request.post(url,files=files)
         6 
         7 

      C:\Users\pavansubhash_t\AppData\Local\Continuum\Anaconda2\lib\site -
    packages\werkzeug\local.pyc in __getattr__(self, name)
         345         if name == '__members__':
    346             return dir(self._get_current_object())
--> 347         return getattr(self._get_current_object(), name)
    348 
    349     def __setitem__(self, key, value):

C:\Users\pavansubhash_t\AppData\Local\Continuum\Anaconda2\lib\site-packages\werkzeug\local.pyc in _get_current_object(self)
    304         """
    305         if not hasattr(self.__local, '__release_local__'):
--> 306             return self.__local()
    307         try:
    308             return getattr(self.__local, self.__name__)

C:\Users\pavansubhash_t\AppData\Local\Continuum\Anaconda2\lib\site-packages\flask\globals.pyc in _lookup_req_object(name)
     35     top = _request_ctx_stack.top
     36     if top is None:
---> 37         raise RuntimeError(_request_ctx_err_msg)
     38     return getattr(top, name)
     39 

RuntimeError: Working outside of request context.

This typically means that you attempted to use functionality that needed an active HTTP request. Consult the documentation on testing for information about how to avoid this problem.

pavan subhash
  • 368
  • 6
  • 14
  • Please post complete error output. Also try to reduce your code to a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve). – Christoph Jul 22 '17 at 08:45
  • @Christoph Edited the code as suggested. Please suggest how can I resolve the issue – pavan subhash Jul 22 '17 at 09:12
  • @pavansubhash please share a minum reproducible example. I think you lost the identation when you pasted to SO. If not, start fixing that, The definition of the post request handler function make_predict is not clear. – Mohamed Ali JAMAOUI Jul 22 '17 at 09:19
  • @MedAli Is it fine now ? My apologies for the inappropriate identation – pavan subhash Jul 22 '17 at 09:32
  • If you could add print after each step, it might help understanding the problem. Otherwise, there is a problem in this line: `return jsonify(results=final_pred_file.to_csv(sub_file))`. You can't jsonfiy a CSV file. The to_csv operation is going to send None, its role is to write to a file in the disk where you are executing your code. If you want to send a JSON, you should use final_pred_file.to_dict(orient="records") – Mohamed Ali JAMAOUI Jul 22 '17 at 09:49
  • Also, there is a mistake in your use of request to upload the file. Check the answer in this question for the correct way to do that https://stackoverflow.com/questions/22567306/python-requests-file-upload – Mohamed Ali JAMAOUI Jul 22 '17 at 09:55
  • Thanks for your comment. What should I do to return my output from the model as a .csv file? – pavan subhash Jul 22 '17 at 10:08
  • you should use send_file. It can be import as follows `from flask import send_file`. Here's an example on how to send an image https://stackoverflow.com/questions/8637153/how-to-return-images-in-flask-response . Customize it to fit your need. – Mohamed Ali JAMAOUI Jul 22 '17 at 11:21
  • @MedAli I tried everything that has been mentioned in above comments. I am getting a connection error: – pavan subhash Jul 22 '17 at 12:01

1 Answers1

1

If I understand well your requirement, you have a pre-trained classifier and you want to serve classification over an API. Your API receives a CSV file as input and sends back another CSV file. To refactor your code to do that, you need to add the follow changes.

Fix how you are sending the file in a request:

Fix the way you are loading the csv file into the files dictionary as follows:

url = 'http://localhost:9000/spend_api'
files = {'file': open('Test_data_final.csv','rb')}
r = request.post(url,files=files)

you can find more details in this SO thread.

Fix how to send the json response

clf_model = joblib.load('MNB_Clf.pkl','r')

app = Flask(__name__)

@app.route('/spend_api',methods=['POST'])
def make_predict():
    data = request.get_json(force=True)

    test_data = pd.read_csv(data)
    pred_proba_class = clf_model.predict_proba(test_data['ColumnName1'])
    final_pred_file = pd.DataFrame(pred_proba_class)
    return jsonify(results=final_pred_file.to_dict(orient="records"))
if __name__ == '__main__':
  app.run(port = 9000,debug=True)

If you want to send a CSV file instead

here is a standalone working example:

from flask import Flask 
from flask import send_file 
from StringIO import StringIO 
import pandas as pd 

app = Flask("csv")

@app.route("/get_csv")
def hello():

    st = """col1|col2
    1|2
    3|4 
    """
    df = pd.read_csv(StringIO(st), sep="|")
    df.to_csv("/tmp/my_test_csv.csv", index=False, sep="|")
    return send_file("/tmp/my_test_csv.csv")


if __name__ == '__main__':
    app.run(port=5000)

As a side note, I suggest that you rethink your design to use JSON instead.

Mohamed Ali JAMAOUI
  • 14,275
  • 14
  • 73
  • 117
  • As I mentioned in the previous comment, now I am getting a ConnectionError: ConnectionError: ('Connection aborted.', error(10054, 'An existing connection was forcibly closed by the remote host')) – pavan subhash Jul 22 '17 at 12:16
  • @pavansubhash your example doesn't reproduce the error. Unless you share a minimum example that I can run on my machine and exactly your error, I can't help you much. In the answer, I tried to give enough information in order to help fix the visible issue. Now, it's up to you. – Mohamed Ali JAMAOUI Jul 22 '17 at 12:24