本文来自网易云社区
作者:王超
问题背景
django框架提供了一个开发调试使用的WSGIServer, 使用这个服务器可以很方便的开发web应用。但是 正式环境下却不建议使用这个服务器, 其性能、安全性都堪忧。一个推荐的做法是使用uwsgi+Nginx来部署django应用。如何使用uwsgi部署不在本文的讨论范围里。
在大多数情况, WSGIServer下的能正常工作的代码, 在uwsgi中也能正常运行。 但是也有很多坑点, 导致uwsgi下的结果与WSGIServer的结果完全不同。 这里就来聊聊这些坑点。
坑点集锦
代码加载顺序
在使用WSGIServer开发时, django应用是通过python manage.py 0.0.0.0:80的命令来启动的, 这个命令对应的python代码就是
from django.core.management import execute_from_command_line execute_from_command_line(sys.argv)
而通过uwsgi部署django时, django应用是通过uwsgi -http 8080 --wsgi-file wsgi来启动的, 这个命令其实就是去加载wsgi.py中的代码
from django.core.wsgi import get_wsgi_application application = get_wsgi_application()
应用的启动方式不同, 导致应用中各个模块的加载顺序也完全不同。
为了研究具体的加载顺序, 我们在ViewBase中加入了以下元类, 这个元类会在所有ViewBase的子类被创建时, 打印出此时的调用堆栈与进程ID(为什么要打印进程id, 后文后解释)
import tracebackclass MetaCls(type): def __new__(cls, name, bases, attrs): pid = os.getpid() print( '%d proc load module: %s' % (pid, attrs["__module__"]) ) print( "".join(traceback.format_stack()) ) return super(MetaCls, cls).__new__(cls, name, bases, attrs)class ViewBase(object): __metaclass__ = MetaCls .......
首先使用python manage.py runserver启动应用, 发现打印出来的信息如下:
2017-04-24 16:22:23,095 __new__[line:231] thread:MainThread: 9428 proc load module: app.BsLogic.Admin.views File "manage.py", line 26, in <module> execute_from_command_line(sys.argv) File "D:\project\qaweb\django\core\management\__init__.py", line 367, in execute_from_command_line utility.execute() ...... #这里省略django内部调用 File "D:\project\qaweb\django\core\checks\urls.py", line 14, in check_url_config # 从这里开始要加载urls了 return check_resolver(resolver) ...... #这里省略django内部