为什么`from django import *`无法导入所有子模块?

时间:2019-12-22 06:40:02

标签: python django

星号(*)在from modue_name import *中用作通配符,表示导入module_name中的所有子模块。

ls /usr/local/lib/python3.5/dist-packages/django
apps  contrib  dispatch  __init__.py  __pycache__   templatetags  utils
bin   core     forms     __main__.py  shortcuts.py  test          views
conf  db       http      middleware   template      urls

位于apps模块中的子模块django

import django
from django import *
print(django.apps)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'django' has no attribute 'apps'

为什么apps无法导入子模块from django import *

5 个答案:

答案 0 :(得分:1)

如果您想在上下文中使用 apps 模块,则可以(至少)通过两种方式进行操作

方法1

import django.apps

print(django.apps)

注意:应为 import django.apps 而不是import django

方法2

from django import apps

print(apps)

使用 from django import * 时,Python仅导入模块(扩展名为.py的文件) {{ 1}} 。即 __init__.py 将不可用,因为它的 不是模块 ,而是

答案 1 :(得分:1)

首先,将需求安装到虚拟环境中而不是系统Python总是一个好主意。值得注意的是,从Python 3.3开始,添加了venv模块,使该过程变得简单。

您遇到的错误与Django中处理模块的过程有关。实际上,在默认控制台和Django Shell中运行时,示例结果之间存在差异。考虑以下示例:

# globally load the module, let's check what's inside.
>>> import django
>>> dir(django)  # only the content from the __init__.py was imported.
['VERSION', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__',
 '__name__', '__package__', '__path__', '__spec__', '__version__', 
'get_version', 'setup', 'utils']
>>> from django import *
>>> print(django.apps)
>>> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'django' has no attribute 'apps'

>>> globals() # no Django submodules were loaded. 

同时在Django shell中运行以上命令:

>>> import django
>>> dir(django)
['VERSION', '__builtins__','__cached__','apps','setup','template',
'templatetags','urls','utils', 'views', ...]
>>> print(django.apps)
>>> <module 'django.apps' from .../django/apps/__init__.py>
>>> globals() # some of the Django submodules were loaded 

在控制台中进行全局Django导入时,将加载__init__.py中的所有内容,并且内部没有直接导入Django子模块的信息。但是,在第一个django导入中的Django shell也可以使用子模块。

答案 2 :(得分:1)

  

星号(*)用作modue_name import *中的通配符,表示导入module_name中的所有子模块。

您是对的,这就是您所做的;您已经在django中导入了所有模块,但是apps是django中的文件夹,这是您必须明确导入该包的另一个包

答案 3 :(得分:0)

__all__中没有django/__init__.py列表。这就是通配符导入from django import *不起作用的原因。

请参见https://docs.python.org/3/tutorial/modules.html#importing-from-a-packageCan someone explain __all__ in Python?

答案 4 :(得分:0)

  

星号(*)用作modue_name import *中的通配符,表示导入module_name中的所有子模块。

排序。

模块

from <module_name> import *中使用星号。如果我们谈论单个模块(单个文件,例如tools.py),它将在模块内导入所有内容。这种模块没有sub_modules,所以说没有道理

  

这意味着导入module_name中的所有子模块。

包裹

但是在这里,我们正在处理一个名为django的软件包;它有一个__init__.py文件,因此是一个程序包。在这种情况下,调用from <package_name> import *会将所有内容导入包的__init__.py文件中,但默认情况下,它将不会导入包中的其他子模块除非,除非您定义了{{1} }列出并在其中包含要由sub_package导出的sub_modules,对象和sub_packages的名称(这是软件包供应商的工作)。即

__all__

该软件包还可以显式导入sub_moudules / sub_packages / objects,并且当使用# __init__.py __all__ = ['apps'] 即导入该软件包时,该软件包才可用。

from <package_name> import *

这又是供应商的工作。

解决方案

但是从代码的角度来看,您只需键入

# __init__.py
import django.apps

干净得多