【发布时间】:2010-11-20 11:25:58
【问题描述】:
如何确定我的应用程序是否在开发服务器上运行?我想我可以检查settings.DEBUG 的值并假设DEBUG 是True 那么它在开发服务器上运行,但我更愿意确定而不是依赖约定。
【问题讨论】:
如何确定我的应用程序是否在开发服务器上运行?我想我可以检查settings.DEBUG 的值并假设DEBUG 是True 那么它在开发服务器上运行,但我更愿意确定而不是依赖约定。
【问题讨论】:
我在 settings.py 中加入了以下内容,以区分标准开发服务器和生产服务器:
import sys
RUNNING_DEVSERVER = (len(sys.argv) > 1 and sys.argv[1] == 'runserver')
不过,这也依赖于约定。
(根据 Daniel Magnusson 的评论修改)
【讨论】:
server = request.META.get('wsgi.file_wrapper', None)
if server is not None and server.__module__ == 'django.core.servers.basehttp':
print('inside dev')
当然,wsgi.file_wrapper 可能会设置在 META 上,并且在另一个服务器环境上非常巧合地具有来自名为 django.core.servers.basehttp 的模块的类,但我希望这能涵盖您。
顺便说一句,我通过在开发服务器上运行时制作了一个语法无效的模板来发现这一点,并在 Traceback 和 Request information 部分搜索有趣的东西,所以我只是编辑我的答案来证实符合 Nate 的想法。
【讨论】:
manage.py 和 wsgi.py (或者保持 DRY,将逻辑添加到第三个文件中,例如 setvars.py 被两者导入和调用)。因此,请使用上述答案或其中另一个答案的逻辑,以便调用os.environ.setdefault('DJANGO_SETTINGS_MODULE','some.settings.module') 的不同变体。这假设您按环境将设置模块分成子模块。再三考虑,上面的答案在那里不起作用,因为尚未设置请求。但你明白了。
wsgiref.util。所以这个 sn-p 不起作用。
wsgiref.util
通常这是有效的:
import sys
if 'runserver' in sys.argv:
# you use runserver
【讨论】:
./manage.py runserver 而不是例如 ./manage.py shell_plus
通常我会设置一个名为environment 的变量并将其设置为“开发”、“暂存”或“生产”。然后,我可以在设置文件中添加基本逻辑,以根据环境更改正在使用的设置。
编辑:此外,您可以简单地使用此逻辑来包含覆盖基本设置的不同settings.py 文件。例如:
if environment == "DEBUG":
from debugsettings import *
【讨论】:
依赖 settings.DEBUG 是 AFAICS 最优雅的方式,因为它有时也用于 Django 代码库。
我想您真正想要的是一种自动设置该标志的方法,而无需每次将项目上传到生产服务器时手动更新它。
为此,我检查了 settings.py 的路径(在 settings.py 中)以确定项目在哪个服务器上运行:
if __file__ == "path to settings.py in my development machine":
DEBUG = True
elif __file__ in [paths of production servers]:
DEBUG = False
else:
raise WhereTheHellIsThisServedException()
请注意,您可能还喜欢按照@Soviut 的建议对环境变量进行此检查。但是作为在 Windows 上开发并在 Linux 上服务的人,检查文件路径比使用环境变量要容易得多。
【讨论】:
WhereTheHellIsThisServedException +1 :-)
我刚才遇到了这个问题,最后写了一个类似于 Aryeh Leib Taurog 的解决方案。我的主要区别是,我想在运行服务器时区分生产环境和开发环境,而且在为我的应用程序运行一些一次性脚本时(我像 DJANGO_SETTINGS_MODULE=settings python [the script] 一样运行)。在这种情况下,仅查看是否 argv[1] == runserver 是不够的。所以我想出的是在我运行开发服务器时传递一个额外的命令行参数,当我运行我的脚本时,只需在 settings.py 中查找该参数。所以代码看起来像这样:
if '--in-development' in sys.argv:
## YES! we're in dev
pass
else:
## Nope, this is prod
pass
那么,运行django服务器就变成了
python manage.py runserver [任何你想要的选项] --in-development
运行我的脚本就这么简单
DJANGO_SETTINGS_MODULE=settings python [myscript] --in-development
只要确保你传递的额外参数不会与任何 django 冲突(实际上我使用我的应用程序名称作为参数的一部分)。 我认为这是相当不错的,因为它让我可以准确控制我的服务器和脚本何时作为 prod 或 dev 运行,而且我不依赖任何其他人的约定,除了我自己的约定。
编辑:如果您传递无法识别的选项,manage.py 会抱怨,因此您需要将 settings.py 中的代码更改为类似
if sys.argv[0] == 'manage.py' or '--in-development' in sys.argv:
# ...
pass
虽然这可行,但我承认它不是最优雅的解决方案...
【讨论】:
如果您想根据运行时环境自动切换设置文件 您可以只使用环境中不同的东西,例如
from os import environ
if environ.get('_', ''):
print "This is dev - not Apache mod_wsgi"
【讨论】:
您可以确定您是在WSGI(mod_wsgi、gunicorn、waitress 等)还是manage.py(运行服务器、测试、迁移等)下运行,还是在其他任何条件下运行:
import sys
WSGI = 'django.core.wsgi' in sys.modules
【讨论】:
settings.DEBUG 可以是 True 并且在 Apache 或其他一些非开发服务器下运行。它仍然会运行。据我所知,在运行时环境中除了检查 pid 并与操作系统中的 pid 进行比较之外,没有什么可以为您提供此信息。
【讨论】:
我用:
DEV_SERVERS = [
'mymachine.local',
]
DEVELOPMENT = platform.node() in DEV_SERVERS
这需要注意.node() 在您的机器上返回的内容。重要的是默认设置为非开发,这样您就不会意外暴露敏感的开发信息。
您也可以查看more complicated ways of uniquely identifying computers。
【讨论】:
开发和部署环境之间的一个区别是运行它的服务器。究竟有什么不同取决于您的开发和部署环境。
了解您自己的开发和部署环境后,HTTP 请求变量可用于区分两者。看看request variables 就像request.META.HTTP_HOST、request.META.SERVER_NAME 和request.META.SERVER_PORT 并在两个环境中比较它们。
我敢打赌,您会发现一些非常明显的不同之处,可用于检测您的开发环境。在settings.py 中进行测试并设置一个您可以在其他地方使用的变量。
【讨论】:
受 Aryeh 回答的启发,我为自己设计的技巧就是在 sys.argv[0] 中查找我的管理脚本的名称:
USING_DEV_SERVER = "pulpdist/manage_site.py" in sys.argv[0]
(我的用例是在运行测试服务器时自动启用 Django 本地身份验证 - 在 Apache 下运行时,即使在开发服务器上,我当前项目的所有身份验证都是通过 Kerberos 处理的)
【讨论】:
你可以检查request.META["SERVER_SOFTWARE"]值:
dev_servers = ["WSGIServer", "Werkzeug"]
if any(server in request.META["SERVER_SOFTWARE"] for server in dev_servers):
print("is local")
【讨论】: