2011-02-23 15 views
13

Usando Flask, ¿cómo puedo obtener el número de puerto actual al que está conectado el matraz? Quiero iniciar un servidor en un puerto aleatorio utilizando el puerto 0, pero también necesito saber en qué puerto estoy.¿Cómo obtener el número de puerto actual en Flask?

Editar

Creo que he encontrado un trabajo en torno a mi problema, aunque no es una respuesta a la pregunta. Puedo recorrer los puertos comenzando con 49152 e intento usar ese puerto a través del app.run(port=PORT). Puedo hacer esto en un bloque try catch para que, si recibo un error Address already in use, pueda probar el siguiente puerto.

+0

mientras raúnning un programa de ejemplo Frasco estoy recibiendo este error: ..... Archivo "/usr/lib/python2.7/socket.py", línea 228, en metanfetamina return getattr (self._sock, name) (* args) socket.error: [Errno 13] Permiso denegado por favor ayúdame cómo puedo cambiar mi puerto –

Respuesta

29

No se puede conseguir fácilmente en el zócalo del servidor utilizado por frasco, ya que está escondido en la parte interna de la biblioteca estándar (Frasco utiliza Werkzeug, cuyo servidor de desarrollo se basa en la stdlib de BaseHTTPServer)

Sin embargo, puede crear un puerto efímero usted mismo y luego cerrar el zócalo que lo crea, luego use ese puerto usted mismo. Por ejemplo:

# hello.py 
from flask import Flask, request 
import socket 

app = Flask(__name__) 

@app.route('/') 
def hello(): 
    return 'Hello, world! running on %s' % request.host 

if __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) 

le dará el número de puerto a utilizar. Un ejemplo de ejecución:

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

y, en navegación a http://localhost:34447/, veo

Hello, world! running on localhost:34447

en mi navegador.

Por supuesto, si algo más que utiliza el puerto entre el usuario cierra el socket y luego Frasco de abrir el aparato con ese puerto, se obtendría una "dirección en uso" error, pero es posible que pueda utilizar esta técnica en tu entorno

0

La mayoría de los sistemas operativos en estos días tienen un comando llamado netstat que le dará una lista de todos los puertos que están actualmente en uso, así como qué aplicaciones se ejecutan en ellos si lo solicita con bastante amabilidad. :)

Debe ser bastante fácil de analizar con os.popen o el módulo subprocess.

Aparte de eso, sólo podía realizar un seguimiento de los puertos que utiliza como empiece a cada servidor ...

Además, si quieres pasar a estar haciendo esto desde el interior de una petición HTTP, usted podría mirar a la SERVER_PORT variable cgi del entorno wsgi.

+2

Siento que debe haber una manera mejor que esta. – david4dev

1

La vinculación al puerto 0 es correcta. Eso hará que el sistema operativo elija un puerto disponible entre 1024 y 65535 para usted.

Para recuperar el puerto elegido después del enlace, use your_socket.getsockname()[1].

Así que todo lo que necesita saber es cómo acceder a la toma de audición que usa Flask.

socket.getsockname() docs: http://docs.python.org/library/socket.html#socket.socket.getsockname

+1

No es tan simple ... Flask no almacena la instancia 'HTTPServer' sino que simplemente la crea y luego llama a' serve_forever() ' –

1

Según lo señalado por @VinaySajip Flask use un socket de servidor estándar pero nunca asigne la instancia a ninguna variable, simplemente contrátela y llame al serve_forever() en línea.

De todos modos, intente extraer el zócalo de la aplicación del matraz, como dijo @ThiefMaster, podemos interceptar la llamada bind_socket() y leer la dirección sin tener en cuenta la creación del zócalo concurrente. Aquí está mi solución:

from flask import Flask, request 
import socketserver 

app = Flask("") 

original_socket_bind = SocketServer.TCPServer.server_bind 
def 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 wrapper 
app.run(port=0, debug=True) 
+0

este es un buen enfoque, pero tiene una caída. cuando uses más código que use TCPServer tu llamada también se llamará para eso, y obtendrás múltiples llamadas a tu función – Fruch

+0

@Fruch tienes razón, esto es solo una prueba de concepto. Quizás sea mejor usar 'mock.patch' en un administrador de contexto' with' para hacerlo de una manera segura y limpia. –

Cuestiones relacionadas