__init__.py 是干什么用的?

秒速五厘米 2024-03-30 11:03 193阅读 0赞

问:

Python 源目录中的 init.py 是什么?

答1:

huntsbot.com – 高效赚钱,自由工作

它曾经是包的必需部分(old, pre-3.3 “regular package”,而不是 newer 3.3+ “namespace package”)。

Here’s the documentation.

Python 定义了两种类型的包,常规包和命名空间包。常规包是 Python 3.2 及更早版本中存在的传统包。常规包通常实现为包含 init.py 文件的目录。当一个常规包被导入时,这个 init.py 文件被隐式执行,它定义的对象被绑定到包的命名空间中的名称。 init.py 文件可以包含任何其他模块可以包含的相同 Python 代码,并且 Python 会在导入模块时为其添加一些附加属性。

但只需点击链接,它包含一个示例、更多信息和命名空间包的说明,即没有 init.py 的包的种类。

这是什么意思:“这样做是为了防止具有通用名称(例如字符串)的目录无意中隐藏模块搜索路径中稍后出现的有效模块”?

@CarlG Python 搜索 list of directories 以解析名称,例如 import 语句。因为这些可以是任何目录,并且最终用户可以添加任意目录,所以开发人员必须担心目录碰巧与有效的 Python 模块共享名称,例如文档示例中的“字符串”。为了缓解这种情况,它会忽略不包含名为 _ _ init _ _.py 的文件(无空格)的目录,即使它是空白的。

@CarlG 试试这个。创建一个名为“datetime”的目录,并在其中创建两个空白文件,init.py 文件(带下划线)和 datetime.py。现在打开一个解释器,导入 sys,然后发出 sys.path.insert(0, '/path/to/datetime'),将该路径替换为您刚刚创建的任何目录的路径。现在试试 from datetime import datetime;datetime.now()。你应该得到一个 AttributeError (因为它现在正在导入你的空白文件)。如果您在不创建空白初始化文件的情况下重复这些步骤,则不会发生这种情况。这就是它要防止的。

我得到的只是ImportError: attempted relative import with no known parent package。我的结构:/PyToHtml init.py pytohtml.py test.py 其中 test.py 有:from .pytohtml import HTML

答2:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

名为 init.py 的文件用于将磁盘上的目录标记为 Python 包目录。如果你有文件

  1. mydir/spam/__init__.py
  2. mydir/spam/module.py

并且 mydir 在您的路径上,您可以将 module.py 中的代码导入为

  1. import spam.module

或者

  1. from spam import module

如果您删除 init.py 文件,Python 将不再在该目录中查找子模块,因此导入模块的尝试将失败。

init.py 文件通常是空的,但可用于以更方便的名称导出包的选定部分、保存方便的函数等。在上面的示例中,可以通过以下方式访问 init 模块的内容

  1. import spam

基于 this

更新:文件 __init__.py 在 Python 2.X 下是必需的,在 Python 2.7.12 下仍然需要(我测试过),但从(据称)Python 3.3 开始不再需要它,在 Python 3.4 下也不需要它。 3(我测试过)。有关详细信息,请参阅 stackoverflow.com/questions/37139786。

为什么你的 init.py 里面有 import spam,它有什么帮助

@alper 他在 __init__.py 中没有 import spam,他在 main.py 或任何需要导入 spam 内容的文件中都有它。您可以将 spam 视为您导入的对象并使用 spam/__init__.py 中定义的函数

答3:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

除了将目录标记为 Python 包并定义 all 之外,init.py 还允许您在包级别定义任何变量。如果包定义了一些将被以类似 API 的方式频繁导入。这种模式促进了对 Pythonic“扁平优于嵌套”哲学的坚持。

一个例子

这是我的一个项目中的一个示例,其中我经常导入一个名为 Session 的 sessionmaker 来与我的数据库交互。我写了一个包含几个模块的“数据库”包:

  1. database/
  2. __init__.py
  3. schema.py
  4. insertions.py
  5. queries.py

我的 init.py 包含以下代码:

  1. import os
  2. from sqlalchemy.orm import sessionmaker
  3. from sqlalchemy import create_engine
  4. engine = create_engine(os.environ['DATABASE_URL'])
  5. Session = sessionmaker(bind=engine)

由于我在这里定义了 Session,我可以使用以下语法开始一个新会话。此代码将在“数据库”包目录内部或外部执行相同。

  1. from database import Session
  2. session = Session()

当然,这是一个小小的便利——替代方法是在我的数据库包中的“create_session.py”之类的新文件中定义 Session,然后使用以下命令启动新会话:

  1. from database.create_session import Session
  2. session = Session()

进一步阅读

这里有一个非常有趣的 reddit 线程,涵盖了 init.py 的适当用法:

http://www.reddit.com/r/Python/comments/1bbbwk/whats\_your\_opinion\_on\_what\_to\_include\_in\_init\_py/

大多数人的意见似乎是 init.py 文件应该非常薄,以避免违反“显式优于隐式”的理念。

engine、sessionmaker、create_engine 和 os 现在也都可以从 database 导入...看起来你把那个命名空间弄得一团糟。

@ArtOfWarfare,您可以使用 __all__ = [...] 来限制通过 import * 导入的内容。但除此之外,是的,你留下了一个凌乱的顶级命名空间。

@NathanGould 您还可以使用默认情况下不由 import * 导入的单个前导下划线变量。例如:import os as _os 并在 __init__.py 模块中使用 _os 代替 os。

答4:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

init.py有两个主要原因

为方便起见:其他用户不需要知道您的函数在您的包层次结构(文档)中的确切位置。 your_package/ init.py file1.py file2.py … fileN.py # in init.py from .file1 import * from .file2 import * … from .fileN import * # in file1.py def add():通过然后其他人可以通过 from your_package import add 调用 add() 而不知道 file1 的内部函数,例如 from your_package.file1 import add 如果您想要初始化某些东西;例如,日志记录(应该放在顶层): import logging.config logging.config.dictConfig(Your_logging_config)

哦,在阅读您的答案之前,我认为从其位置显式调用函数是一种好习惯。

@Aerin最好不要将简短的陈述(或者,在这种情况下,主观结论)视为始终正确。从 __init__.py 导入有时可能有用,但并非总是如此。

init.py 里面必须有什么?

答5:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

init.py 文件使 Python 将包含它的目录视为模块。

此外,这是要在模块中加载的第一个文件,因此您可以使用它来执行每次加载模块时要运行的代码,或指定要导出的子模块。

我认为 init.py 使 Python 将目录视为 packages 而不是 modules。请参阅docs.python.org/3/tutorial/modules.html

“所有包都是模块,但并非所有模块都是包”——很奇怪,但确实如此。

答6:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

从 Python 3.3 开始,不再需要 init.py 将目录定义为可导入的 Python 包。

检查PEP 420: Implicit Namespace Packages:

对不需要 init.py 标记文件并且可以自动跨越多个路径段的包目录的本机支持(受命名空间包的各种第三方方法的启发,如 PEP 420 中所述)

这是测试:

  1. $ mkdir -p /tmp/test_init
  2. $ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
  3. $ tree -at /tmp/test_init
  4. /tmp/test_init
  5. ├── module.py
  6. └── __init__.py
  7. $ python3
  8. >>> import sys
  9. >>> sys.path.insert(0, '/tmp')
  10. >>> from test_init import module
  11. >>> import test_init.module
  12. $ rm -f /tmp/test_init/__init__.py
  13. $ tree -at /tmp/test_init
  14. /tmp/test_init
  15. └── module.py
  16. $ python3
  17. >>> import sys
  18. >>> sys.path.insert(0, '/tmp')
  19. >>> from test_init import module
  20. >>> import test_init.module

参考: https://docs.python.org/3/whatsnew/3.3.html\#pep-420-implicit-namespace-packages https://www.python.org/dev/peps/pep-0420/ Is init.py not required for packages in Python 3?

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

它是“命名空间”包。不要将其用于常规包装。

@methan,你能详细说明你的评论吗?

@RobertLugg 见dev.to/methane/don-t-omit-init-py-3hga

答7:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

尽管 Python 可以在没有 init.py 文件的情况下工作,但您仍应包含一个。

它指定目录应该被视为一个包,因此包含它(即使它是空的)。

还有一种情况是您可能会实际使用 init.py 文件:

假设您有以下文件结构:

  1. main_methods
  2. |- methods.py

methods.py 包含以下内容:

  1. def foo():
  2. return 'foo'

要使用 foo(),您需要以下条件之一:

  1. from main_methods.methods import foo # Call with foo()
  2. from main_methods import methods # Call with methods.foo()
  3. import main_methods.methods # Call with main_methods.methods.foo()

也许您需要(或想要)将 methods.py 保留在 main_methods 中(例如运行时/依赖项),但您只想导入 main_methods。

如果您将 methods.py 的名称更改为 init.py,则只需导入 main_methods 即可使用 foo():

  1. import main_methods
  2. print(main_methods.foo()) # Prints 'foo'

这是因为 init.py 被视为包的一部分。

一些 Python 包实际上是这样做的。以 JSON 为例,其中运行 import json 实际上是从 json 包 (see the package file structure here) 导入 init.py:

源代码:Lib/json/init.py

答8:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

在 Python 中,包的定义非常简单。与 Java 一样,层次结构和目录结构是相同的。但是您必须在一个包中包含 init.py。我将通过以下示例解释 init.py 文件:

  1. package_x/
  2. |-- __init__.py
  3. |-- subPackage_a/
  4. |------ __init__.py
  5. |------ module_m1.py
  6. |-- subPackage_b/
  7. |------ __init__.py
  8. |------ module_n1.py
  9. |------ module_n2.py
  10. |------ module_n3.py

init.py 可以为空,只要它存在。它表示该目录应该被视为一个包。当然,init.py也可以设置相应的内容。

如果我们在module_n1中添加一个函数:

  1. def function_X():
  2. print "function_X in module_n1"
  3. return

运行后:

  1. >>>from package_x.subPackage_b.module_n1 import function_X
  2. >>>function_X()
  3. function_X in module_n1

然后我们按照层次包调用module_n1这个函数。我们可以像这样在 subPackage_b 中使用 init.py:

  1. __all__ = ['module_n2', 'module_n3']

运行后:

  1. >>>from package_x.subPackage_b import *
  2. >>>module_n1.function_X()
  3. Traceback (most recent call last):
  4. File "", line 1, in
  5. ImportError: No module named module_n1

因此使用 * 导入,模块包受 init.py 内容的约束。

我的 setup.py 如何通过打包的库进行相同的导入? from package_x.subPackage_b.module_n1 import function_X

所以这里的关键是“使用 * 导入,模块包受 init.py 内容的影响”

答9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

init.py 会将其所在的目录视为可加载模块。

对于喜欢阅读代码的人,我在这里放了 Two-Bit Alchemist’s 评论。

  1. $ find /tmp/mydir/
  2. /tmp/mydir/
  3. /tmp/mydir//spam
  4. /tmp/mydir//spam/__init__.py
  5. /tmp/mydir//spam/module.py
  6. $ cd ~
  7. $ python
  8. >>> import sys
  9. >>> sys.path.insert(0, '/tmp/mydir')
  10. >>> from spam import module
  11. >>> module.myfun(3)
  12. 9
  13. >>> exit()
  14. $
  15. $ rm /tmp/mydir/spam/__init__.py*
  16. $
  17. $ python
  18. >>> import sys
  19. >>> sys.path.insert(0, '/tmp/mydir')
  20. >>> from spam import module
  21. Traceback (most recent call last):
  22. File "", line 1, in
  23. ImportError: No module named spam
  24. >>>

答10:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

它有助于导入其他 python 文件。当您将此文件放在包含其他 py 文件的目录(例如东西)中时,您可以执行诸如 import stuff.other 之类的操作。

  1. root\
  2. stuff\
  3. other.py
  4. morestuff\
  5. another.py

如果目录 stuff 中没有此 init.py,您将无法导入 other.py,因为 Python 不知道 stuff 的源代码在哪里,并且无法将其识别为包。

答11:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

init.py 文件使导入变得容易。当包中存在 init.py 时,可以从文件 b.py 导入函数 a(),如下所示:

  1. from b import a

但是,没有它,您将无法直接导入。您必须修改系统路径:

  1. import sys
  2. sys.path.insert(0, 'path/to/b.py')
  3. from b import a

原文链接:https://www.huntsbot.com/qa/bLOA/what-is-init-py-for?lang=zh_CN&from=csdn

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

发表评论

表情:
评论列表 (有 0 条评论,193人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AHK2EXE什么

    AHK2EXE 是用来将 AutoHotkey 脚本编译成独立的可执行文件的工具。AutoHotkey 是一种开源的软件,它可以用来创建自动化任务和快捷键的脚本。AHK2EXE