使用Flask,如何獲得燒瓶連接的當前端口號?我想使用端口0在隨機端口上啓動服務器,但我也需要知道我在哪個端口上。如何獲取Flask中的當前端口號?
編輯
我想我已經找到一個變通爲我的問題,但它不是一個問題的答案。我可以遍歷從49152開始的端口,並嘗試通過app.run(port=PORT)
使用該端口。我可以在try catch塊中這樣做,這樣如果我得到一個Address already in use
錯誤,我可以嘗試下一個端口。
使用Flask,如何獲得燒瓶連接的當前端口號?我想使用端口0在隨機端口上啓動服務器,但我也需要知道我在哪個端口上。如何獲取Flask中的當前端口號?
編輯
我想我已經找到一個變通爲我的問題,但它不是一個問題的答案。我可以遍歷從49152開始的端口,並嘗試通過app.run(port=PORT)
使用該端口。我可以在try catch塊中這樣做,這樣如果我得到一個Address already in use
錯誤,我可以嘗試下一個端口。
你不能很容易地得到在由瓶使用的服務器套接字,因爲它隱藏在標準庫的內部(瓶使用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/,我看到
Hello, world! running on localhost:34447
在我的瀏覽器。
當然,如果其他東西在你關閉套接字之間使用了那個端口,然後Flask用這個端口打開套接字,你會得到一個「Address in use」錯誤,但是你也許能夠使用這種技術你的環境。
目前大多數操作系統都有一個叫做netstat
的命令,它會給你一個當前正在使用的所有端口的列表,以及如果你問得很好的話,它們上面正在運行哪些應用程序。 :)
它應該很容易與os.popen
或subprocess
模塊解析。
除此之外,你可以只跟蹤您正在使用的端口,當你開始每個服務器...
另外,如果你碰巧從HTTP請求中這樣做,你可以看看SERVER_PORT cgi變量來自wsgi環境。
我覺得必須有比這更好的方法。 – david4dev 2011-02-23 07:46:18
綁定到端口0是正確的。這將使操作系統爲您選擇1024到65535之間的可用端口。
要在綁定後檢索選定的端口,請使用your_socket.getsockname()[1]
。
因此,您需要了解的是如何訪問Flask使用的偵聽套接字。
socket.getsockname()
文檔:http://docs.python.org/library/socket.html#socket.socket.getsockname
不是那麼簡單.... Flask不存儲'HTTPServer'實例,但只是創建它,然後調用'serve_forever()' – 2014-12-20 21:28:28
正如@VinaySajip所指出的一樣,Flask使用標準服務器套接字,但它從不將該實例分配給任何變量,只是構造它並調用serve_forever()
。
不管怎麼說,我們可以攔截bind_socket()
調用並讀取地址,而無需考慮併發套接字的創建,而是嘗試從flask應用中提取套接字作爲@ThiefMaster。這裏是我的解決方案:
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)
這是一個好方法,但它有一個垮臺。當使用更多使用TCPServer的代碼時,您的電話也將被調用,並且您將接到多個電話給您的功能 – Fruch 2017-01-06 05:41:21
@Fruch您是對的,這只是一個概念證明。也許最好在'with'上下文管理器中使用'mock.patch'來以安全和乾淨的方式進行操作。 – 2017-01-06 17:41:05
而raúnning樣本瓶節目我收到此錯誤:.....文件「/usr/lib/python2.7/socket.py」,線路228,在甲基 返回getattr(self._sock,name)(* args) socket.error:[Errno 13]權限被拒絕 請幫助我如何更改端口 – 2016-12-07 10:48:15