如何从 views.py 以 Popen() 开始的脚本导入 Django 模型?
How to import Django models from script started with Popen() from views.py?
我想在某个请求到达我的 Django 服务器时在不同的进程中启动一个 python 脚本。
我可以成功启动它,但是导入失败。
在我的 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后端的models,所以和之前一样:
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
中的第一个模型 class 开始,然后深入到 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 以某种方式干扰了我的导入,但我不确定如何以及如何纠正它们。
如何成功导入(和使用)django app from a python script that's started with subprocess.Popen(...)
from views.py
of django-rest-framework 的 models.py
?
来自评论
Is Process.py a regular Python script, or is it written as a Django Management Command?
楷书。
我出于调试目的修改了它:
import sys
for p in sys.path:
print(p)
from . import models
What happens if you run the script manually from the shell? Same error?
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
可能您缺少对 Django 应用程序 的引用,要从中导入所有模型,您必须在 python 脚本:
from <django-app-name>.models import *
Process.py
应该是一个 Django Management Command,这样 Django Framework 就会被加载并且 model.py
被 Django 使用。
PYTHONPATH
仍然是必需的,以便 Django 知道基本目录在哪里。
Instad of ["python", filename]
,进程可以从 ["python", "manage.py", filename]
开始。
我想在某个请求到达我的 Django 服务器时在不同的进程中启动一个 python 脚本。 我可以成功启动它,但是导入失败。
在我的 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后端的models,所以和之前一样:
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
中的第一个模型 class 开始,然后深入到 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 以某种方式干扰了我的导入,但我不确定如何以及如何纠正它们。
如何成功导入(和使用)django app from a python script that's started with subprocess.Popen(...)
from views.py
of django-rest-framework 的 models.py
?
来自评论
Is Process.py a regular Python script, or is it written as a Django Management Command?
楷书。 我出于调试目的修改了它:
import sys
for p in sys.path:
print(p)
from . import models
What happens if you run the script manually from the shell? Same error?
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 |
可能您缺少对 Django 应用程序 的引用,要从中导入所有模型,您必须在 python 脚本:
from <django-app-name>.models import *
Process.py
应该是一个 Django Management Command,这样 Django Framework 就会被加载并且 model.py
被 Django 使用。
PYTHONPATH
仍然是必需的,以便 Django 知道基本目录在哪里。
Instad of ["python", filename]
,进程可以从 ["python", "manage.py", filename]
开始。