mod_wsgi (Apache)¶
如果你使用的是 Apache 网络服务器 ,可以考虑使用 mod_wsgi 。
注意
请提前确认把 app.run()
放在 if __name__ == '__main__':
代码块中或者放在单独的文件中,这样可以确保它不会被调用。因为每调用一次就会开启一个本地的 WSGI 服务器,如果我们将应用部署到 mod_wsgi,并不需要开启本地服务器。
安装 mod_wsgi¶
如果你还没有安装 mod_wsgi,你可以使用包管理器安装或者自行编译。在 UNIX 系统中如何以源代码形式安装 mod_wsgi 请参考 安装操作。
如果你使用的是 Ubuntu/Debian 系统,你可以使用如下的 apt-get 命令来安装并启用:
$ apt-get install libapache2-mod-wsgi-py3
如果你使用的是基于 yum 的发行版(Fedora、OpenSUSE 等)的系统,你可以这样安装:
$ yum install mod_wsgi
在 FreeBSD 系统中,可以通过编译 www/mod_wsgi 或是使用 pkg_add 来安装 mod_wsgi:
$ pkg install ap24-py37-mod_wsgi
如果你使用 pkgsrc,可以通过编译 www/ap2-wsgi 包来安装 mod_wsgi。
如果你在第一次 apache 重新加载后遇到子进程段错误的话,不必理会,重启服务器即可。
创建一个 .wsgi 文件¶
你需要一个 yourapplication.wsgi
文件才能启动你的应用。该文件包含 mod_wsgi 启动时所需要运行的代码,通过代码可以获取到应用对象。文件中的 application 对象就是之后使用到的应用。
对大多数应用来说,文件中包含以下内容就足够了:
from yourapplication import app as application
如果你在 __init__.py
文件中使用到了工厂函数,那么该函数应当被导入:
from yourapplication import create_app
application = create_app()
如果你没有一个用来创建应用的工厂函数,而是一个单例,那么可以直接把它导入为 application。
把文件放在以后能找得到的地方(比如:/var/www/yourapplication
),并确保 yourapplication 和所有使用到的库都位于 Python 加载路径中。如果你不想在系统环境中安装,你可以考虑使用 虚拟 Python 实例。请记住,这时你也需要将你的应用程序安装到虚拟环境中。另外一个选项是在 .wsgi
文件中的导入语句前加入路径:
import sys
sys.path.insert(0, '/path/to/the/application')
配置 Apache¶
最后,你要为你的应用创建一个 Apache 配置文件。在下面的例子中,出于安全考虑,我们让 mod_wsgi 用另一个用户执行应用程序:
<VirtualHost *>
ServerName example.com
WSGIDaemonProcess yourapplication user=user1 group=group1 threads=5
WSGIScriptAlias / /var/www/yourapplication/yourapplication.wsgi
<Directory /var/www/yourapplication>
WSGIProcessGroup yourapplication
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
注意:WSGIDaemonProcess 未在 Windows 中实现,并且 Apache 将拒绝以上述配置运行。在 Windows 中,请删除这些行:
<VirtualHost *>
ServerName example.com
WSGIScriptAlias / C:\yourdir\yourapp.wsgi
<Directory C:\yourdir>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
注意:Apache 2.4 的访问控制配置发生了一些改变。
最值得注意的是,目录权限的语法已经从 httpd 2.2
Order allow,deny
Allow from all
变更为 httpd 2.4 的语法
Require all granted
想要了解更多信息,请参考 mod_wsgi 文档。
故障排除¶
如果你的应用没有启动,请按照以下指导排除故障:
- Problem: application does not run, errorlog shows SystemExit ignored
你的应用文件中有
app.run()
调用,但并未放入if __name__ == '__main__':
。要么把run()
的调用从文件移除,放入一个单独的run.py
文件中,否则请将它让入 if 块中。- Problem: application gives permission errors
有可能是使用了错误的用户去启动应用。请检查你的用户及其所在的组(WSGIDaemonProcess 的
user
和group
参数)是否有权限访问应用所在的文件夹- 问题: 应用在打印时抛出错误并终止
请记住 mod_wsgi 不允许使用
sys.stdout
以及sys.stderr
。你可以把 WSGIRestrictStdout 设置为off
来关闭这个保护机制:WSGIRestrictStdout Off
或者你也可以在 .wsgi 文件中使用不同的流(stream)替代标准输出:
import sys sys.stdout = sys.stderr
- 问题: 访问资源时 IO 错误
你的应用可能是一个单独的 .py 文件,并且你把它软连接到了 site-packages 文件夹中。这样是不起作用的,你必须把文件夹放入文件所在的 Python 路径中,或者把你的应用转换成包。
产生这种错误的原因是对于非安装包来说,模块的文件名用于定位资源,如果使用软连接的话就会定位到错误的文件名。
支持自动重载¶
为了辅助部署工具,你可以激活自动重载。这样,一旦 .wsgi
文件有所变动,mod_wsgi 就会自动重新加载所有守护进程。
在 Directory 这一节中加入以下指令即可实现自动重载:
WSGIScriptReloading On
在虚拟环境中工作¶
使用虚拟环境的优点是不必在系统范围安装应用所需的依赖,这样就可以更好地控制哪里需要什么。如果要在虚拟环境下使用 mod_wsgi,那么我们要对 .wsgi
文件略作改变。
在你的 .wsgi
文件顶部加入下面这行:
activate_this = '/path/to/env/bin/activate_this.py'
with open(activate_this) as file_:
exec(file_.read(), dict(__file__=activate_this))
这样设置,就会根据虚拟环境的设置加载路径。请记住,必须是绝对路径。