一直在用flask写一些小型的后台服务。有余力之下,去研究了一下flask的源码。不得不赞叹flask对于python的运用之炉火纯青。下面开始分析。
flask框架使用了库werkzeug,werkzeug是基于WSGI的,WSGI是什么呢?(Web Server Gateway Interface),WSGI是一个协议,通俗翻译Web服务器网关接口,该协议把接收自客户端的所有请求都转交给这个对象处理。
基于如上背景知识,这里不只是研究了flask的源码,也会把涉及到的werkzeug库的源码,以及werkzeug库使用到的python基本库的源码列出来,力求能够把整个逻辑给陈列清楚。
服务类
Flask:
应用程序类,该类直接面向用户。所有的Flask程序都必须创建这样一个程序实例。简单点儿可以app=Flask(__name__),Flask可以利用这个参数决定程序的根目录。
* 类成员:
Request
Response
* 类方法:
run
run方法调用werkzeug库中的一个run_simple函数来启动BaseWSGIServer。
def run_simple(hostname, port, application, use_reloader=False,
use_debugger=False, use_evalex=True,
extra_files=None, reloader_interval=1,
reloader_type='auto', threaded=False,
processes=1, request_handler=None, static_files=None,
passthrough_errors=False, ssl_context=None):
if use_debugger:
from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(application, use_evalex)
if static_files:
from werkzeug.wsgi import SharedDataMiddleware
application = SharedDataMiddleware(application, static_files)
def inner():
try:
fd = int(os.environ['WERKZEUG_SERVER_FD'])
except (LookupError, ValueError):
fd = None
make_server(hostname, port, application, threaded,
processes, request_handler,
passthrough_errors, ssl_context,
fd=fd).serve_forever()
if use_reloader:
# If we're not running already in the subprocess that is the
# reloader we want to open up a socket early to make sure the
# port is actually available.
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
if port == 0 and not can_open_by_fd:
raise ValueError('Cannot bind to a random port with enabled '
'reloader if the Python interpreter does '
'not support socket opening by fd.')
# Create and destroy a socket so that any exceptions are
# raised before we spawn a separate Python interpreter and
# lose this ability.
address_family = select_ip_version(hostname, port)
s = socket.socket(address_family, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((hostname, port))
if hasattr(s, 'set_inheritable'):
s.set_inheritable(True)
# If we can open the socket by file descriptor, then we can just
# reuse this one and our socket will survive the restarts.
if can_open_by_fd:
os.environ['WERKZEUG_SERVER_FD'] = str(s.fileno())
s.listen(LISTEN_QUEUE)
else:
s.close()
from ._reloader import run_with_reloader
run_with_reloader(inner, extra_files, reloader_interval,
reloader_type)
else:
inner()
make_server创建