How to get the current port number in Flask? How to get the current port number in Flask? flask flask

How to get the current port number in Flask?


You can't easily get at the server socket used by Flask, as it's hidden in the internals of the standard library (Flask uses Werkzeug, whose development server is based on the stdlib's BaseHTTPServer).

However, you can create an ephemeral port yourself and then close the socket that creates it, then use that port yourself. For example:

# hello.pyfrom flask import Flask, requestimport socketapp = Flask(__name__)@app.route('/')def hello():    return 'Hello, world! running on %s' % request.hostif __name__ == '__main__':    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    sock.bind(('localhost', 0))    port = sock.getsockname()[1]    sock.close()    app.run(port=port)

will give you the port number to use. An example run:

$ python hello.py * Running on http://127.0.0.1:34447/

and, on browsing to http://localhost:34447/, I see

Hello, world! running on localhost:34447

in my browser.

Of course, if something else uses that port between you closing the socket and then Flask opening the socket with that port, you'd get an "Address in use" error, but you may be able to use this technique in your environment.


As pointed by @VinaySajip Flask use standard server socket but it never assign the instance to any variable, just construct it and call serve_forever() in line.

Anyway instead try to extract socket from flask's app as said @ThiefMaster, we can intercept bind_socket() call and read the address without take care of concurrent socket creation. Here is my solution:

from flask import Flask, requestimport socketserverapp = Flask("")original_socket_bind = SocketServer.TCPServer.server_binddef socket_bind_wrapper(self):    ret = original_socket_bind(self)    print("Socket running at {}:{}".format(*self.socket.getsockname()))    # Recover original implementation    socketserver.TCPServer.server_bind = original_socket_bind    return ret@app.route("/")def hello():    return 'Hello, world! running on {}'.format(request.host)socketserver.TCPServer.server_bind = socket_bind_wrapper   #Hook the wrapperapp.run(port=0, debug=True)


I agree with the accepted answer that

You can't easily get at the server socket used by Flask, as it's hidden in the internals of the standard library (Flask uses Werkzeug, whose development server is based on the stdlib's BaseHTTPServer).

However, I just discovered that Werkzeug exposes an option to pass a file descriptor for use as it's socket when running werkzeug.serving.BaseWSGIServer (which is what flask's run() function ends up doing). Using this functionality it is possible to select a random available port and then tell Werkzeug to use it.

Here is the startup of my application:

import loggingimport pprintimport sysfrom flask import Flaskapplog = logging.getLogger(__name__)applog.setLevel(logging.INFO)app = Flask(__name__)if __name__ == '__main__':    app.config.from_object('myapp.default_settings')    try:        app.config.from_envvar('MYAPP_SETTINGS')    except RuntimeError:        applog.warning("MYAPP_SETTINGS environment variable not set or invalid. Using default settings.")    # SERVER_NAME should be in the form of localhost:5000, 127.0.0.1:0, etc...    # So, split on : and take the second element as the port    # If the port is 0, we need to pick a random port and then tell the server to use that socket    if app.config['SERVER_NAME'] and int(app.config['SERVER_NAME'].split(':')[1]) == 0:        import socket, os        # Chose a random available port by binding to port 0        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        sock.bind((app.config['SERVER_NAME'].split(':')[0], 0))        sock.listen()        # Tells the underlying WERKZEUG server to use the socket we just created        os.environ['WERKZEUG_SERVER_FD'] = str(sock.fileno())        # Update the configuration so it matches with the port we just chose        # (sock.getsockname will return the actual port being used, not 0)        app.config['SERVER_NAME'] = '%s:%d' % (sock.getsockname())    # Optionally write the current port to a file on the filesystem    if app.config['CREATE_PORT_FILE']:        with open(app.config['PORT_FILE'], 'w') as port_file:            port_file.write(app.config['SERVER_NAME'].split(':')[1])    applog.info("Running app on %s" % (app.config['SERVER_NAME']))    applog.info("Active Settings:%s" % pprint.pformat(app.config, compact=True))    app.run()

Contents of myapp.default_settings:

SERVER_NAME = '127.0.0.1:0'PORT_FILE = 'current_port'CREATE_PORT_FILE = True

The important bit here is setting os.environ['WERKZEUG_SERVER_FD']. Werkzeug looks at this environment variable during the run_simple function and, if it is defined, passes it as the fd parameter to the make_server function. This eventually is used as the socket for communication.

While I can't guarantee the stability of this approach (I don't know how well supported the WERKZEUG_SERVER_FD environment variable is) I prefer it to the suggested solutions so far because:

  1. I don't have to loop through a range of ports catching exceptions, I just get the first available port straight from the OS.
  2. There is no chance my chosen random port gets taken between the time I bind a random port and when I run the application because the port I am binding is the port my application ends up using.

The code above also logs the port being used and optionally writes the current port being used to a file specified by a configuration option.