【发布时间】:2021-06-06 11:34:51
【问题描述】:
当某个请求到达我的 django 服务器时,我想在不同的进程中启动一个 python 脚本。 我可以成功启动它,但它的导入失败。
在我的 django 应用程序中,我有一个 views.py。
在这我有一个ViewSet 和一个update() 方法,看起来像这样(将sn-p 简化为相关代码):
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中编写导入语句:from models import stuff奇怪的是,这确实导入了
models.py(耶!)但在兔子洞的深处失败了:ModuleNotFoundError: No module named '<django project name>'说的兔子洞从
models.py中的第一个模型类开始,然后潜入 django 代码,最后是一些引导程序: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>\lib\site-packages\django\db\models\base.py", line 108, in __new__ app_config = apps.get_containing_app_config(module) File "<path to conda environment>\lib\site-packages\django\apps\registry.py", line 253, in get_containing_app_config self.check_apps_ready() File "<path to conda environment>\lib\site-packages\django\apps\registry.py", line 135, in check_apps_ready settings.INSTALLED_APPS File "<path to conda environment>\lib\site-packages\django\conf\__init__.py", line 82, in __getattr__ self._setup(name) File "<path to conda environment>\lib\site-packages\django\conf\__init__.py", line 69, in _setup self._wrapped = Settings(settings_module) File "<path to conda environment>\lib\site-packages\django\conf\__init__.py", line 170, in __init__ mod = importlib.import_module(self.SETTINGS_MODULE) File "<path to conda environment>\lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level)看起来 django 以某种方式干扰了我的导入,但我不确定如何以及如何纠正它们。
如何从以subprocess.Popen(...) 开头的views.py 的django-rest-framework 的python 脚本成功导入(和使用)models.py 的django 应用程序?
来自 cmets
Process.py 是一个普通的 Python 脚本,还是作为 Django 管理命令编写的?
这是一个常规脚本。 我出于调试目的对其进行了修改,如下所示:
import sys
for p in sys.path:
print(p)
from . import models
如果您从 shell 手动运行脚本会发生什么?同样的错误?
| from shell | django views.py via Popen()
|
|
|---|---|---|
windows cmd: django-project>python manage.py shell then In [1]: from django-app import Process
|
see above | call detail |
| success | ImportError: cannot import name 'models' |
result |
includes django-project path and empty path |
includes django-project/django-app
|
differences of sys.path
|
【问题讨论】:
-
Process.py是普通的 Python 脚本,还是写成 Django Management Command?如果从 shell 手动运行脚本会发生什么?同样的错误? -
@C14L 只是一个普通的 python 脚本(单独的
import语句会重现错误)。感谢您的建议。我正在对 django 的命令进行更多研究,based on this anser。我设法创建了一个自定义命令并通过manage.py使用工作导入执行它,但是:我将如何将它作为一个单独的进程执行? -
我只是在猜测:将
PYTHONPATH保留在上面的示例中,并将["python", filename]更改为["python", "manage.py", filename]。 -
@C14L 你让我走上了正确的道路:根据你的建议,我能够调用我之前提到的
Process.py的 Django-Management-Comment 版本并解决了我的担忧“但是:我将如何将其作为一个单独的进程执行?” - 只需在永远不会返回的句柄方法中执行while True:,这很好,因为调用仍然包含在Popen()中。谢谢。随时发布作为答案。 -
很高兴它起作用了 :) 我将其添加为答案。
标签: django django-rest-framework python django-models django-rest-framework subprocess modulenotfounderror