首先,推薦一個便宜的雲主機,感覺比阿里便宜,新用戶一年68元,滴滴雲
附上活動鏈接:https://i.didiyun.com/2d7Jy4Nzle8
Flask的最小應用程序如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
app.run()
Flask的類從flask包中引入後,直接製造app實例,使用app實例執行run方法。
所以先來看看Flask類中的_init__()和run()方法
def __init__(
# 這裏用的比較多的是,static_folder,static_url_path靜態目錄的指定,實例中都是默認參數
self,
import_name,
static_url_path=None,
static_folder="static",
static_host=None,
host_matching=False,
subdomain_matching=False,
template_folder="templates",
instance_path=None,
instance_relative_config=False,
root_path=None,
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
try:
run_simple(host, port, self, **options)
finally:
self._got_first_request = False
run方法中省略調試相關的代碼,關鍵執行代碼是run_simple方法,帶入默認的host和port以及對象,host爲127.0.0.1,port爲5000。那麼就來分析run_simple()
run_simple()
run_simple方法來自werkzeug中的serving.py。
def run_simple(
hostname,
port,
application
):
def inner():
try:
fd = int(os.environ["WERKZEUG_SERVER_FD"])
except (LookupError, ValueError):
fd = None
srv = make_server(
hostname,
port,
application,
threaded,
processes,
request_handler,
passthrough_errors,
ssl_context,
fd=fd,
)
if fd is None:
log_startup(srv.socket)
srv.serve_forever()
inner()
run_simple()主要是執行了inner(),inner中初始化srv實例後執行srv.serve_forever()方法。先看make_server()方法,根據進程和線程使用不同的類進行初始化,且這些類都繼承了BaseWSGIServer。
def make_server(
host=None,
port=None,
app=None,
threaded=False,
processes=1,
request_handler=None,
passthrough_errors=False,
ssl_context=None, fd=None,):
if threaded and processes > 1:
raise ValueError("cannot have a multithreaded and multi process server.")
elif threaded:
return ThreadedWSGIServer(省略 )
elif processes > 1:
return ForkingWSGIServer(省略 )
else:
return BaseWSGIServer(省略 )
這裏以BaseWSGIServer爲例進行分析。BaseWSGIServer繼承HTTPServer,這裏帶入的參數除了host,port還有handler,sWSGIRequestHandler,WSGIRequestHandler繼承BaseHTTPRequestHandler。主要是爲了實現http的數據請求和發送。
class BaseWSGIServer(HTTPServer, object): """Simple single-threaded, single-process WSGI server."""
multithread = False
multiprocess = False
def __init__(
self,
host,
port,
app,
handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,):
if handler is None:
handler = WSGIRequestHandler
先看一下執行函數,serve_forever,執行的是 HTTPServer.serve_forever()
def serve_forever(self):
self.shutdown_signal = False
try:
HTTPServer.serve_forever(self)
except KeyboardInterrupt:
pass
finally:
self.server_close()
爲了更好的說明,把WSGIRequestHandler和BaseWSGIServer繼承過來,單獨運行獲得http的響應。
from werkzeug.serving import WSGIRequestHandler,BaseWSGIServer
class New_Handler(WSGIRequestHandler):
page = '''\
<html>
<body>
<p>hello</p>
</body>
</html>
'''
def do_GET(self):
current_path = self.path
# self.send_error(415,'your url is %s' % current_path)
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.send_header("Content-Length", 100)
self.end_headers()
self.wfile.write(self.page.encode('utf-8'))
tcp_server = BaseWSGIServer(host="127.0.0.1",port=5000,app=None,handler=New_Handler)
if __name__ == "__main__":
tcp_server.serve_forever()
既然http的請求響應入口已經找到了,那麼就來看看請求路由的處理,所以要研究裝飾器@app.route('/'),來看看Flask中路由處理思路。
裝飾器如下:
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
# 路由裝飾器的使用
@app.route('/')
def hello_world():
return "hello_world"
以簡單根目錄請求爲例,通過裝飾器可以看出,首先執行self.add_url_rule(rule, endpoint, f, **options),然後再執行實例方法hello_world()。