Flask を使用して、flaskが接続されている現在のポート番号を取得するにはどうすればよいですか?ポート0を使用してランダムなポートでサーバーを起動したいのですが、必要です私がどのポートにいるのかを知るために。
編集
質問に対する答えではありませんが、問題の回避策を見つけたと思います。 49152から始まるポートを反復処理し、app.run(port=PORT)
を介してそのポートの使用を試みることができます。これはtrycatchブロックで実行できるので、Address already in use
エラー、次のポートを試すことができます。
Flaskが使用するサーバーソケットは、標準ライブラリの内部に隠されているため、簡単に取得することはできません(FlaskはWerkzeugを使用します。Werkzeugの開発サーバーはstdlibのBaseHTTPServer
に基づいています)。
ただし、エフェメラルポートを自分で作成し、それを作成するソケットを閉じてから、そのポートを自分で使用することができます。例えば:
# 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)
使用するポート番号が表示されます。実行例:
$ python hello.py
* Running on http://127.0.0.1:34447/
そして、 http:// localhost:34447 / を参照すると、
こんにちは世界! localhost:34447で実行中
私のブラウザで。
もちろん、ソケットを閉じてからFlaskそのポートでソケットを開く間に他の何かがそのポートを使用する場合、「使用中のアドレス」エラーが発生しますが、可能かもしれませんご使用の環境でこの手法を使用します。
@VinaySajip Flaskは標準のサーバーソケットを使用しますが、インスタンスを変数に割り当てることはありません。インスタンスを作成してserve_forever()
を順番に呼び出すだけです。
とにかく、@ ThiefMasterが言ったように、代わりにフラスコのアプリからソケットを抽出しようとすると、同時ソケットの作成を気にせずにbind_socket()
呼び出しをインターセプトし、アドレスを読み取ることができます。これが私の解決策です:
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)
私は受け入れられた答えに同意します
Flaskが使用するサーバーソケットは、標準ライブラリの内部に隠されているため、簡単に取得することはできません(Flaskは、開発サーバーがstdlibのBaseHTTPServerに基づいているWerkzeugを使用しています)。
しかし、Werkzeugが_werkzeug.serving.BaseWSGIServer
_(フラスコのrun()
関数が最終的に実行すること)を実行するときにソケットとして使用するためにファイル記述子を渡すオプションを公開していることを発見しました。この機能を使用すると、使用可能なランダムなポートを選択して、Werkzeugにそれを使用するように指示することができます。
これが私のアプリケーションの起動です:
_import logging
import pprint
import sys
from flask import Flask
applog = 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()
_
_myapp.default_settings
_の内容:
_SERVER_NAME = '127.0.0.1:0'
PORT_FILE = 'current_port'
CREATE_PORT_FILE = True
_
ここで重要なのは、_os.environ['WERKZEUG_SERVER_FD']
_の設定です。 Werkzeugは、_run_simple
_関数の実行中にこの環境変数を調べ、定義されている場合は、それをfd
パラメーターとして_make_server
_関数に渡します。これは最終的に通信用のソケットとして使用されます。
このアプローチの安定性を保証することはできませんが(_WERKZEUG_SERVER_FD
_環境変数がどの程度サポートされているかはわかりません)、これまでに提案されたソリューションよりも次の理由でそれを好みます。
上記のコードは、使用されているポートもログに記録し、オプションで、現在使用されているポートを構成オプションで指定されたファイルに書き込みます。
ポート0へのバインドは正しいです。これにより、オペレーティングシステムは1024〜65535の使用可能なポートを選択するようになります。
バインド後に選択したポートを取得するには、your_socket.getsockname()[1]
を使用します。
したがって、知る必要があるのは、リスニングソケットにアクセスする方法Flask usesです。
socket.getsockname()
docs: http://docs.python.org/library/socket.html#socket.socket.getsockname
最近のほとんどのオペレーティングシステムには、netstat
というコマンドがあり、現在使用されているすべてのポートのリストと、十分に質問があれば、それらのポートで実行されているアプリケーションが表示されます。 :)
os.popen
またはsubprocess
モジュールを使用して解析するのは非常に簡単です。
それとは別に、各サーバーを起動するときに使用しているポートを追跡することもできます...
また、httpリクエスト内からこれを実行している場合は、wsgi環境からSERVER_PORTcgi変数を確認できます。