我想在不同的进程中启动一个python脚本,当一个特定的请求到达我的django服务器。我可以成功启动它,但是它的导入失败。
在我的django应用程序中,我有一个views.py
。在这里,我有一个ViewSet
与update()
方法,看起来像这样(减少片段到相关代码):
from . import models # notice this import, which works
def update(self, request, pk=None):
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'Process.py')
p = subprocess.Popen(["python", filename],
stdout=sys.stdout,
stdin=subprocess.PIPE)
按预期工作:当执行导致调用update()
的适当请求时,它执行Process.py
,这是与views.py
在同一目录中的文件。
在Process.py
中,我想访问django后端的模型,所以我像以前一样做:
from . import models
# more code here
但是我得到错误:
ImportError: cannot import name 'models'
为什么在Process.py
中导入失败,即使它适用于views.py
?
我试着
在互联网上的建议,环境应该设置为相同的子进程,像这样:
p = subprocess.Popen(["python", filename], env = {'PYTHONPATH': os.pathsep.join(sys.path)}, # this is new stdout=sys.stdout, stdin=subprocess.PIPE)
但这根本无法启动python:
Fatal Python error: failed to get random numbers to initialize Python
以不同的方式编写
Process.py
中的import语句:from models import stuff
奇怪的是,这确实导入了
models.py
(哇!),但在更深入的兔子洞中失败了:ModuleNotFoundError: No module named '<django project name>'
兔子洞从
models.py
的第一个模型类开始,然后潜入django代码,结束于一些bootstrapper:Traceback (most recent call last): File "<path to django app>Process.py", line 1, in <module> from models import stuff File "<path to django app>models.py", line 3, in <module> class <some model class>(models.Model): File "<path to conda environment>libsite-packagesdjangodbmodelsbase.py", line 108, in __new__ app_config = apps.get_containing_app_config(module) File "<path to conda environment>libsite-packagesdjangoappsregistry.py", line 253, in get_containing_app_config self.check_apps_ready() File "<path to conda environment>libsite-packagesdjangoappsregistry.py", line 135, in check_apps_ready settings.INSTALLED_APPS File "<path to conda environment>libsite-packagesdjangoconf__init__.py", line 82, in __getattr__ self._setup(name) File "<path to conda environment>libsite-packagesdjangoconf__init__.py", line 69, in _setup self._wrapped = Settings(settings_module) File "<path to conda environment>libsite-packagesdjangoconf__init__.py", line 170, in __init__ mod = importlib.import_module(self.SETTINGS_MODULE) File "<path to conda environment>libimportlib__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level)
看起来django在某种程度上干扰了我的导入,但我不确定如何以及如何纠正它们。
我如何成功地导入(和使用)models.py
的django应用程序从一个python脚本的subprocess.Popen(...)
从django-rest-framework的views.py
开始?
来自注释
Process.py是一个普通的Python脚本,还是一个Django管理命令?
这是一个普通的脚本。为了调试,我对它进行了如下修改:
import sys
for p in sys.path:
print(p)
from . import models
如果在shell中手动运行脚本会发生什么?同样的错误吗?
from shell | djangoviews.py viaPopen() | |
---|---|---|
windows cmd:django-project>python manage.py shell thenIn [1]: from django-app import Process | 见上文 | call detail |
ImportError: cannot import name 'models' | 结果 | |
包含django-project 路径和空路径 | 包含django-project/django-app | sys.path |
Process.py
应该是Django管理命令,以便Django加载Django框架并使用model.py
。
PYTHONPATH
仍然是必需的,以便Django知道基本目录在哪里。
可以用["python", "manage.py", filename]
代替["python", filename]
启动进程。
可能你错过了对你的Django应用的引用,到导入所有模型从它,你必须在python脚本中做:
from <django-app-name>.models import *