从哪开始阅读源代码¶
代码树¶
执行命令:
tree -I '*.pyc'
先看看gunicorn的目录树:
gunicorn
├── app
│ ├── base.py
│ ├── djangoapp.py
│ ├── __init__.py
│ ├── pasterapp.py
│ └── wsgiapp.py
├── arbiter.py
├── config.py
├── debug.py
├── errors.py
├── glogging.py
├── http
│ ├── body.py
│ ├── errors.py
│ ├── __init__.py
│ ├── message.py
│ ├── parser.py
│ ├── _sendfile.py
│ ├── unreader.py
│ └── wsgi.py
├── __init__.py
├── logging_config.py
├── management
│ ├── commands
│ │ ├── __init__.py
│ │ └── run_gunicorn.py
│ └── __init__.py
├── pidfile.py
├── sock.py
├── util.py
└── workers
├── async.py
├── base.py
├── geventlet.py
├── ggevent.py
├── ggevent_wsgi.py
├── gtornado.py
├── __init__.py
├── sync.py
└── workertmp.py
从脚本命令开始¶
就从脚本命令gunicorn和gunicorn_django开始
gunicorn
#!/home/hzg/mypy/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'gunicorn==0.13.4','console_scripts','gunicorn'
__requires__ = 'gunicorn==0.13.4'
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('gunicorn==0.13.4', 'console_scripts', 'gunicorn')()
)
gunicorn_django
#!/home/hzg/mypy/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'gunicorn==0.13.4','console_scripts','gunicorn_django'
__requires__ = 'gunicorn==0.13.4'
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('gunicorn==0.13.4', 'console_scripts', 'gunicorn_django')()
)
这是eggs文件的规范,实际上调用入口,可以从entry_points.txt看出来:
entry_points.txt:
[console_scripts]
gunicorn=gunicorn.app.wsgiapp:run
gunicorn_django=gunicorn.app.djangoapp:run
gunicorn_paster=gunicorn.app.pasterapp:run
注意在[console_scripts]部分,有
- gunicorn <–> gunicorn.app.wsgiapp:run
- gunicorn_django <–> gunicorn.app.djangoapp:run
那么,我们就从gunicorn/app目录下开始,从wsgiapp.py, djangoapp.py开始。
wsgiapp.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import os
import sys
from gunicorn import util
from gunicorn.app.base import Application
class WSGIApplication(Application):
def init(self, parser, opts, args):
if len(args) != 1:
parser.error("No application module specified.")
self.cfg.set("default_proc_name", args[0])
self.app_uri = args[0]
sys.path.insert(0, os.getcwd())
def load(self):
return util.import_app(self.app_uri)
def run():
"""\
The ``gunicorn`` command line runner for launcing Gunicorn with
generic WSGI applications.
"""
from gunicorn.app.wsgiapp import WSGIApplication
WSGIApplication("%prog [OPTIONS] APP_MODULE").run()
|
gunicorn.app.wsgiapp:run最终是调用其中的一个函数run(),焦点集中在上述代码的最后两行,创建WSGIApplication后,立刻执行run()。
djangoapp.py¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | ENVIRONMENT_VARIABLE = 'DJANGO_SETTINGS_MODULE'
class DjangoApplication(Application):
def init(self, parser, opts, args):
self.global_settings_path = None
self.project_path = None
if args:
self.global_settings_path = args[0]
if not os.path.exists(os.path.abspath(args[0])):
self.no_settings(args[0])
def get_settings_modname(self):
from django.conf import ENVIRONMENT_VARIABLE
# get settings module
settings_modname = None
if not self.global_settings_path:
project_path = os.getcwd()
# ......
def setup_environ(self, settings_modname):
from django.core.management import setup_environ
# setup environ
# ......
def no_settings(self, path, import_error=False):
if import_error:
error = "Error: Can't find '%s' in your PYTHONPATH.\n" % path
# .......
def activate_translation(self):
from django.conf import settings
from django.utils import translation
translation.activate(settings.LANGUAGE_CODE)
def validate(self):
""" Validate models. This also ensures that all models are
imported in case of import-time side effects."""
from django.core.management.base import CommandError
from django.core.management.validation import get_validation_errors
# ......
def load(self):
from django.core.handlers.wsgi import WSGIHandler
self.setup_environ(self.get_settings_modname())
self.validate()
self.activate_translation()
return WSGIHandler()
# ......
def run():
"""\
The ``gunicorn_django`` command line runner for launching Django
applications.
"""
from gunicorn.app.djangoapp import DjangoApplication
DjangoApplication("%prog [OPTIONS] [SETTINGS_PATH]").run()
|
gunicorn.app.djangoapp:run最终是调用其中的一个函数run(),焦点集中在上述代码的最后两行,创建DjangoApplication后,立刻执行run()。
尽管DjangoApplication定义了不少方法,但注意与WSGIAppliction的骨架一样,实际上就定义了两个方法:
- init()
- load()
最关键的方法run(),估计就是从父类Application里继承而来。