Python 如何在console_脚本中调用django.setup()?
当前的django文档告诉我: django.setup()只能调用一次 因此,避免将可重用的应用程序逻辑放在独立脚本中,这样您就必须从应用程序中其他地方的脚本导入。如果无法避免,请将对django.setup()的调用放在If块中: 资料来源: 我正在setup.py中使用入口点。这样我就没有了Python 如何在console_脚本中调用django.setup()?,python,django,python-import,freeze,Python,Django,Python Import,Freeze,当前的django文档告诉我: django.setup()只能调用一次 因此,避免将可重用的应用程序逻辑放在独立脚本中,这样您就必须从应用程序中其他地方的脚本导入。如果无法避免,请将对django.setup()的调用放在If块中: 资料来源: 我正在setup.py中使用入口点。这样我就没有了\uuuuu name\uuuuu=='\uuuuu main\uuuuuuu' 问题: 如果使用,如何确保只调用一次django.setup() 我应该把django.setup()放在哪里 背景 我
\uuuuu name\uuuuu=='\uuuuu main\uuuuuuu'
问题:
如果使用,如何确保只调用一次django.setup()
我应该把django.setup()放在哪里
背景
我的实际错误是:Django挂起。原因如下:
我想将我的应用程序移植到当前的django版本。更改为管理命令不是一个选项,因为其他(第三方应用程序)依赖于my console脚本的存在。也有同样的问题(或类似问题)。我通过以下方式解决了这个问题:
[警告:溶液不干净]
if not hasattr(django, 'apps'):
django.setup()
这样,即使多次导入,它也只会被调用一次。这里我们可以看到django.setup的实际功能
配置设置(这是访问
第一个设置),配置日志记录并填充应用程序注册表。
如果Set\u prefix
为True,则设置线程本地urlresolvers脚本前缀
因此,基本上,为了确保安装已经完成,我们可以检查应用程序是否准备就绪,设置是否已配置
from django.apps import apps
from django.conf import settings
if not apps.ready and not settings.configured:
django.setup()
因为我喜欢无条件代码,所以我使用这个解决方案。这与django文档中的情况类似,但ulgy
if uuuuuu name\uuuuuuu=='\uuuuu pain\uuuuu'
可以避免
带代码的文件:
# utils/do_good_stuff.py
# This file contains the code
# No `django.setup()` needed
# This code can be used by web apps and console scripts.
from otherlib import othermethod
def say_thank_you():
...
主服务器的文件:
# do_good_stuff_main.py
import django
django.setup()
def say_thank_you_main():
from myapp import do_good_stuff
return do_good_stuff()
setup.py:
'console_scripts': [
'say_thank_you=myapp.do_good_stuff_main:say_thank_you_main',
...
这是我目前的解决方案。欢迎回来。有什么需要改进的吗?我在两个生产CLI python软件包中使用了
console\u脚本中显式调用django.setup()
您应该注意的最重要的事情是env
路径中的DJANGO\u设置\u模块
您可以在shell脚本中设置此值,甚至可以在python脚本中加载默认设置
下面是一个例子:
# setup.py
entry_points={
'my-cli = mypackage.cli:main'
}
在Django 2.2.5(至少)中,设置是在导入时配置的django.setup()
配置它们,因为它会导入它们。调用django.setup()
两次的问题在于,您将填充settings.INSTALLED\u apps
中指定的应用两次,这可能会导致各种问题
如果不是apps.ready:
检查是您应该使用的全部内容,因此:
import django
if not apps.ready:
django.setup()
如果未使用(apps.ready或settings.configured):
-则使用是错误的,因为设置可能已在其他地方配置了导入语句,并且应用可能尚未填充,因此在需要时可能不会调用django.setup()
也就是说,如果你知道你的独立入口点(例如,main.py
),你可以在没有条件的情况下调用它。仅当存在实际运行脚本两次的风险时,才需要该条件,可能是将您的独立模块导入另一个独立模块,以便它们都调用django.setup。多次导入一个模块只会运行一次。有什么错误吗?还可以提及您正在尝试做的事情,因为在做需要django环境的事情时,a可能是更干净的解决方案。@BernhardVallant我更新了问题。更改为管理命令不是一个选项。您引用的文档表明,可以通过将包含“可重用应用程序逻辑”的脚本分为两部分来避免此问题:a)不可重用的脚本代码并调用django.setup()
b)可重用应用程序逻辑它可以由脚本和任何其他需要它的东西导入,并且不调用django.setup()
。为什么你不能这样做?@Louis是的,我可以将代码分为“脚本”和“可重用的应用程序逻辑”。但这会产生不稳定的代码:AFAIK我可以测试脚本,除非通过子流程调用它。这使得嘲弄变得不可能。如果删除“如果不是…”会发生什么。换句话说,如果django.setup()被调用两次会发生什么?@guettli它可能会失败,并出现raiseruntimeerror(“设置已配置”)
。因为它将再次尝试配置设置。但是apps.populate应该不会有任何问题,因为如果self.ready:return,它会这样做,所以基本上你的解决方案就是完全按照我在对你的问题的评论中建议的去做。@Louis是的。还有一个问题:do\u good\u stuff\u main.py
将第二次调用django.setup()。
# cli.py
import logging
from os import environ as env
if not 'DJANGO_SETTINGS_MODULE' in env:
from mypackage import settings
env.setdefault('DJANGO_SETTINGS_MODULE', settings.__name__)
import django
django.setup()
# this line must be after django.setup() for logging configure
logger = logging.getLogger('mypackage')
def main():
# to get configured settings
from django.conf import settings
# do stuffs
if __name__ == '__main__':
main()
import django
if not apps.ready:
django.setup()