从包中导入python

and*_*dio 7 python import packages

文件夹结构:

<current dir>
   main.py
   packages <dir>
      __init__.py
      mod.py
Run Code Online (Sandbox Code Playgroud)

主要的py:

import packages
print packages.mod.hello()
Run Code Online (Sandbox Code Playgroud)

mod.py:

def hello():
    return 'hello'
Run Code Online (Sandbox Code Playgroud)

__init__.py:

from packages import mod
Run Code Online (Sandbox Code Playgroud)

如果我跑main.py,我没有错误.但是,如果我编辑__init__.py'from packages import *',我得到这个错误:AttributeError的:"模块"对象有没有属性"国防部"

我不是在问这个'print'命令如何工作.我可以使用其他'import'语法main.py使其工作.现在的问题是:我很好奇的是'from packages import mod'__init__.py.如果我可以这样做,import mod当我替换import *,这意味着导入一切,为什么我会得到一个错误?

那么from packages import *内心真正意味着__init__.py什么呢?

有人可以帮忙吗?谢谢

Mik*_*ler 12

简短的回答

那么from packages import *内心真正意味着__init__.py什么呢?

__init__.py进口本身.

说明

您只能导入模块,而不能导入包.包只是模块或子包的容器.当您"导入"包时,实际导入模块__init__.py.

__init__.py与此内容:

from packages import mod
Run Code Online (Sandbox Code Playgroud)

将模块mod导入__init__.py.因此,它将在您的main.pyvia中可用packages.mod(记住packages由表示__init__.py).

当您将内容更改__init__.py为:

from packages import *
Run Code Online (Sandbox Code Playgroud)

您正在导入模块__init__.py,即您所在的文件.这样可行(第二次导入只会触发查找sys.modules)但不会为您提供内容mod.

这意味着,您可以使用:

from module import *
Run Code Online (Sandbox Code Playgroud)

但你不能明智地使用它__init__.py:

from package import *
Run Code Online (Sandbox Code Playgroud)

因为package实际上是由__init__.py它代表的,并且它还没有.你可以检查这个(交互式或文件中):

>>> import packages
>>> print(packages)
<module 'packages' from '/.../packages/__init__.py'>
Run Code Online (Sandbox Code Playgroud)

__init__.py你可以写:

from packages.mod import *
Run Code Online (Sandbox Code Playgroud)

然后在main.py:

print packages.hello()
Run Code Online (Sandbox Code Playgroud)

作品.因为该函数hello()现在位于文件的全局名称空间中__init__.py.

作为由mozman的答复中提到,您可以使用__all____init__.py列出的模块应导入如果from packages import *使用.这是专为这种情况设计的.

__init__.py只有这些内容:

__all__ = ['mod']
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做main.py:

from packages import *

print mod.hello()
Run Code Online (Sandbox Code Playgroud)

如果你扩展你的__init__.py:

__all__ = ['mod']

from packages import *
Run Code Online (Sandbox Code Playgroud)

你可以这样做main.py:

import packages

print packages.mod.hello()
Run Code Online (Sandbox Code Playgroud)

但是,如果你删除from packages import *__init__.py:

__all__ = ['mod'] 
Run Code Online (Sandbox Code Playgroud)

你会收到一个错误:

AttributeError: 'module' object has no attribute 'mod'
Run Code Online (Sandbox Code Playgroud)

因为__all__它仅用于from packages import *案例.现在我们回到__init__.py进口本身.