Why is python-requests to localhost slow?

Question:

I have a simple flask server defined like so:

import sys

import flask
from flask import request

app = flask.Flask(__name__)
port = 4057

@app.route('/search', methods=['POST'])
def search():
  request.json['query']
  results = ['fake', 'data']
  return flask.jsonify(results)

if __name__ == '__main__':
 app.config['TEMPLATES_AUTO_RELOAD'] = True
 app.run(host='0.0.0.0', port=port, debug=(port != 80))

I have a simple client defined like this:

import json

import requests

headers = {'content-type': 'application/json'}
resp = requests.post('http://localhost:4057/search', json.dumps({'query': 'foo'}), headers=headers)
print resp.content

The client works, but it takes like 3 seconds to complete the request.

curl completes in like half a second:

curl 'http://localhost:4057/search' -H 'Content-Type: application/json' -d '{"query": "foo"}'

Asked By: Jesse Aldridge

||

Answers:

Try 127.0.0.1 There maybe some odd name resolution rules fumbling requests.

Ah ok, this is my work machine. I took a look at /etc/hosts and saw ~200 routes defined that I didn’t realize were there

As mention in the comments, this does not explain the odd behavior replicated using curl.

Answered By: salparadise

For those trying to figure this out as no one gave a clear solution here:

I encountered this issue a while ago, and noticed that the Flask test server is not concurrent. The Python Requests takes FOREVER to retrieve the data from your flask app unless you make it concurrent. Enabling “Threaded” in your app.run option will do the trick!

app.run(port=5000, debug=True, threaded=True)
Answered By: Yongju Lee

I’ve recently encountered a similar issue with slow connections from requests to ‘localhost’, and also found that using ‘127.0.0.1’ was much faster.

After some investigation, I found that in my case, the slow connections on Windows were related to urllib3 (the transport library used by requests) attempting an IPv6 connection first, which is refused since the server is listening on IPv4 only. For Windows only, however, there is an unavoidable 1 sec timeout on socket.connect for refused TCP connections, while the OS ‘helpfully’ retries the connection up to 3 times. (See: Why do failed attempts of Socket.connect take 1 sec on Windows?).

On Linux, socket.connect fails immediately if the connection is refused, and it can attempt the IPv4 connection without any delay. In addition, some software, like curl, support limiting name resolution to only IPv4 or IPv6. Unfortunately, requests and urllib3 do not support this, and do not seem to plan to support this anytime soon (See: https://github.com/psf/requests/issues/1691)

Answered By: forcedude0
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.