Python __init__.py 文件

本文详细介绍了Python中的_init_.py文件的作用,包括标识软件包、控制模块导入和模糊导入。通过实例展示了如何在_init_.py中重命名导入模块的别名,以及如何使用__all__变量实现模糊导入。讨论了不使用完整包名导入导致的错误,并解释了导入子模块时__all__的重要性。最后,提供了关于正确导入子模块的方法。
摘要由CSDN通过智能技术生成

Python _init_.py 文件

_init_.py主要作用:
  • Python文件结构中用来识别软件包(package)的标志,如果其他文件中有对这个目录下文件中类的调用,则不能删除
  • 可以通过定义__all__用于模糊导入
_init_.py用于import目录中的类

通常_init_.py文件中我们不写入任何字符,只需要将文件放入对应软件包所在目录,即可对该文件中的类对象进行调用。

├── feudal_networks
│   ├── __init__.py
│   ├── __pycache__
│   │   └── __init__.cpython-37.pyc
│   ├── algos
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   ├── __init__.cpython-37.pyc
│   │   │   └── policy_optimizer.cpython-37.pyc
│   │   ├── feudal_policy_optimizer.py
│   │   └── policy_optimizer.py
│   ├── envs
│   │   ├── __init__.py
│   │   ├── debug_envs.py
│   │   └── vision_maze.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── __pycache__
│   │   │   ├── __init__.cpython-37.pyc
│   │   │   └── models.cpython-37.pyc
│   │   └── models.py
│   └── policies
│       ├── __init__.py
│       ├── __pycache__
│       │   ├── __init__.cpython-37.pyc
│       │   └── lstm_policy.cpython-37.pyc
│       ├── configs
│       │   ├── __init__.py
│       │   ├── feudal_config.py
│       │   └── lstm_config.py
│       ├── feudal_batch_processor.py
│       ├── feudal_policy.py
│       ├── lstm_policy.py
│       ├── policy.py
│       └── policy_utils.py
_init_.py用于控制模块导入

我们想对algos目录下的policy_optimizer.py和feudal_policy_optimizer.py文件在import的时候将名称替换为更容易记住的名称,则需要在feudal_networks目录下的_init_.py文件中添加如下语句:

from feudal_networks.algos import policy_optimizer as poz
from feudal_networks.algos import feudal_policy_optimizer as fpo

# 调用
>>> from feudal_networks import poz
# 调用没有问题

为什么这里不能直接使用algos目录下做相对import?

from algos import policy_optimizer as poz
from algos import feudal_policy_optimizer as fpo

# 如果这样调用则会报错
>>> import feudal_networks
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/scotty/Desktop/feudal_networks-master/feudal_networks/__init__.py", line 1, in <module>
    from algos import policy_optimizer as poz
ModuleNotFoundError: No module named 'algos'

这里是因为在我们执行import时,当前目录的相对路径是会改变的,所以我们在_init_.py文件中import需要使用完整的包名。

__all__模糊导入

如果对feudal_networks目录下的_init_.py文件增加如下内容:

__all__ = ["models"] 		# 只导入models模块,不处理algos和policies模块

# 调试
# 当我们从feudal_networks导入所有包时,可以看到
>>> from feudal_networks import *
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'models']
>>> dir(models)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

可以看到在总的类目录中可以看到models包,但当我们查看models包内的内容时,会发现models目录下的模块没有被导入(子模块内容未被导入)。

这就需要查看官方文档中关于从包中导入的描述了:

The only solution is for the package author to provide an explicit index of the package. The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered. It is up to the package author to keep this list up-to-date when a new version of the package is released. Package authors may also decide not to support it, if they don’t see a use for importing * from their package. For example, the file sound/effects/__init__.py could contain the following code:

__all__ = ["echo", "surround", "reverse"]
This would mean that from sound.effects import * would import the three named submodules of the sound package.

If __all__ is not defined, the statement from sound.effects import * does not import all submodules from the package sound.effects into the current namespace; it only ensures that the package sound.effects has been imported (possibly running any initialization code in __init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements. Consider this code:

如果在models目录下的_init_.py对all不定义,并且不显式导入子模块,则默认不会将models模块下的任意子块导入到当前的命名空间中,这也是为什么models模块下为空的问题。

正确的导入方法是在models模块下init文件中写入需要导入的包:

__all__ = ['models']
from feudal_networks.models import models

# 调试
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'models']
>>> dir(models)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'models']

则可以正确的导入子模块。

Reference:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值