__init__.py 是做什么用的?

发布于 2024-07-13 02:30:32 字数 134 浏览 8 评论 0原文

什么是 __init__.py Python源目录?

What is __init__.py for in a Python source directory?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

对你而言 2024-07-20 02:30:32

它曾经是包的必需部分(old, pre-3.3 "常规包”,而不是较新的 3.3+“命名空间包”< /a>)。

这是文档。

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

但只需单击链接,它包含一个示例、更多信息以及命名空间包的说明,即没有 __init__.py 的包。

It used to be a required part of a package (old, pre-3.3 "regular package", not newer 3.3+ "namespace package").

Here's the documentation.

Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an __init__.py file. When a regular package is imported, this __init__.py file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The __init__.py file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.

But just click the link, it contains an example, more information, and an explanation of namespace packages, the kind of packages without __init__.py.

梦冥 2024-07-20 02:30:32

名为 __init__.py 的文件用于将磁盘上的目录标记为 Python 包目录。
如果您有这些文件

mydir/spam/__init__.py
mydir/spam/module.py

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

import spam.module

from spam import module

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

__init__.py 文件通常为空,但可用于以更方便的名称导出包的选定部分,保存方便的函数等。
鉴于上面的示例,可以访问 init 模块的内容,因为

import spam

此答案基于 此网页

Files named __init__.py are used to mark directories on disk as Python package directories.
If you have the files

mydir/spam/__init__.py
mydir/spam/module.py

and mydir is on your path, you can import the code in module.py as

import spam.module

or

from spam import module

If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.

The __init__.py file is usually empty, but can be used to export selected portions of the package under more convenient name, hold convenience functions, etc.
Given the example above, the contents of the init module can be accessed as

import spam

This answer is based on this webpage.

空袭的梦i 2024-07-20 02:30:32

除了将目录标记为 Python 包并定义 __all__ 之外,__init__.py 还允许您在包级别定义任何变量。如果一个包以类似 API 的方式定义了经常导入的内容,那么通常会很方便。 这种模式促进了对 Pythonic“扁平优于嵌套”哲学的坚持。

示例

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

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

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

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

由于我在这里定义了 Session,我可以使用以下语法启动一个新会话以下。 该代码与从“database”包目录内部或外部执行的代码相同。

from database import Session
session = Session()

当然,这是一个小小的便利 - 另一种方法是在我的数据库包中的新文件(例如“create_session.py”)中定义 Session ,并使用以下命令启动新会话:

from database.create_session import Session
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 文件应该非常薄,以避免违反“明确的是比隐含的更好”的哲学。

In addition to labeling a directory as a Python package and defining __all__, __init__.py allows you to define any variable at the package level. Doing so is often convenient if a package defines something that will be imported frequently, in an API-like fashion. This pattern promotes adherence to the Pythonic "flat is better than nested" philosophy.

An example

Here is an example from one of my projects, in which I frequently import a sessionmaker called Session to interact with my database. I wrote a "database" package with a few modules:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

My __init__.py contains the following code:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Since I define Session here, I can start a new session using the syntax below. This code would be the same executed from inside or outside of the "database" package directory.

from database import Session
session = Session()

Of course, this is a small convenience -- the alternative would be to define Session in a new file like "create_session.py" in my database package, and start new sessions using:

from database.create_session import Session
session = Session()

Further reading

There is a pretty interesting reddit thread covering appropriate uses of __init__.py here:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

The majority opinion seems to be that __init__.py files should be very thin to avoid violating the "explicit is better than implicit" philosophy.

ι不睡觉的鱼゛ 2024-07-20 02:30:32

__init__.py

为了方便起见,有两个主要原因

  1. :其他用户不需要知道您的函数在包层次结构中的确切位置(文档)。

    your_package/ 
        __init__.py 
        文件1.py 
        文件2.py 
          ... 
        文件N.py 
      

    __init__.py 中的

    # 
      从 .file1 导入 * 
      从 .file2 导入 * 
      ... 
      从 .fileN 导入 * 
      

    file1.py 中的

    # 
      def 添加(): 
          经过 
      

    然后其他人可以通过以下方式调用add()

     from your_package import add 
      

    不知道 file1 的内部函数,例如

     from your_package.file1 import add 
      
  2. ,例如

    如果你想要初始化某些东西; 例如,日志记录(应放在顶层):

     导入logging.config 
       logging.config.dictConfig(Your_logging_config) 
      

There are 2 main reasons for __init__.py

  1. For convenience: the other users will not need to know your functions' exact location in your package hierarchy (documentation).

    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():
        pass
    

    then others can call add() by

     from your_package import add
    

    without knowing file1's inside functions, like

     from your_package.file1 import add
    
  2. If you want something to be initialized; for example, logging (which should be put in the top level):

     import logging.config
     logging.config.dictConfig(Your_logging_config)
    
椵侞 2024-07-20 02:30:32

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

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

The __init__.py file makes Python treat directories containing it as modules.

Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.

迷离° 2024-07-20 02:30:32

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

检查 PEP 420:隐式命名空间包

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

这是测试:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> 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/
Python 3 中的包不需要 __init__.py 吗?

Since Python 3.3, __init__.py is no longer required to define directories as importable Python packages.

Check PEP 420: Implicit Namespace Packages:

Native support for package directories that don’t require __init__.py marker files and can automatically span multiple path segments (inspired by various third party approaches to namespace packages, as described in PEP 420)

Here's the test:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

references:
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?

猫性小仙女 2024-07-20 02:30:32

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

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

还有一种情况,您实际上可能使用 __init__.py 文件:

假设您有以下文件结构:

main_methods 
    |- methods.py

方法.py 包含这个:

def foo():
    return 'foo'

要使用 foo() 你需要以下之一:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

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


如果您将 methods.py 的名称更改为 __init__.py,那么您只需导入 main_methods 即可使用 foo() code>:

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

这是有效的,因为 __init__.py 被视为包的一部分。


一些 Python 包实际上就是这样做的。 一个示例是 JSON,其中运行 import json实际上是从 json 包中导入 __init__.py (在此处查看包文件结构):

源代码: Lib/json/__init__.py

Although Python works without an __init__.py file you should still include one.

It specifies that the directory should be treated as a package, so therefore include it (even if it is empty).

There is also a case where you may actually use an __init__.py file:

Imagine you had the following file structure:

main_methods 
    |- methods.py

And methods.py contained this:

def foo():
    return 'foo'

To use foo() you would need one of the following:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

Maybe there you need (or want) to keep methods.py inside main_methods (runtimes/dependencies for example) but you only want to import main_methods.


If you changed the name of methods.py to __init__.py then you could use foo() by just importing main_methods:

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

This works because __init__.py is treated as part of the package.


Some Python packages actually do this. An example is with JSON, where running import json is actually importing __init__.py from the json package (see the package file structure here):

Source code: Lib/json/__init__.py

乖乖公主 2024-07-20 02:30:32

在Python中,包的定义非常简单。 与Java 一样,层次结构和目录结构是相同的。 但是你必须在包中包含 __init__.py 。 我将用下面的例子解释__init__.py文件:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

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

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

def function_X():
    print "function_X in module_n1"
    return

运行后:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

然后我们按照层次结构包,调用 module_n1 函数。 我们可以在 subPackage_b 中使用 __init__.py,如下所示:

__all__ = ['module_n2', 'module_n3']

运行后:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

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

In Python the definition of package is very simple. Like Java the hierarchical structure and the directory structure are the same. But you have to have __init__.py in a package. I will explain the __init__.py file with the example below:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py can be empty, as long as it exists. It indicates that the directory should be regarded as a package. Of course, __init__.py can also set the appropriate content.

If we add a function in module_n1:

def function_X():
    print "function_X in module_n1"
    return

After running:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Then we followed the hierarchy package and called module_n1 the function. We can use __init__.py in subPackage_b like this:

__all__ = ['module_n2', 'module_n3']

After running:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Hence using * importing, module package is subject to __init__.py content.

梦境 2024-07-20 02:30:32

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

对于喜欢阅读代码的人,我在这里添加了两位炼金术士的评论。

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

__init__.py will treat the directory it is in as a loadable module.

For people who prefer reading code, I put Two-Bit Alchemist's comment here.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 
梦醒灬来后我 2024-07-20 02:30:32

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

root\
    stuff\
         other.py

    morestuff\
         another.py

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

It facilitates importing other python files. When you placed this file in a directory (say stuff)containing other py files, then you can do something like import stuff.other.

root\
    stuff\
         other.py

    morestuff\
         another.py

Without this __init__.py inside the directory stuff, you couldn't import other.py, because Python doesn't know where the source code for stuff is and unable to recognize it as a package.

情愿 2024-07-20 02:30:32

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

from b import a

没有它,但是,您不能直接导入。 需要修改系统路径:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

An __init__.py file makes imports easy. When an __init__.py is present within a package, function a() can be imported from file b.py like so:

from b import a

Without it, however, you can't import directly. You have to amend the system path:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a
凶凌 2024-07-20 02:30:32

__init__.py 允许的一件事是将模块转换为包,而不会破坏 API 或创建无关的嵌套命名空间或私有模块*。 当我想扩展命名空间时这会很有帮助。

如果我有一个包含 util.py 的文件

def foo():
    ...

,那么用户将通过以下方式访问 foo

from util import foo

如果我想添加用于数据库交互的实用程序函数,并且我希望他们在 util 下拥有自己的命名空间code>,我需要一个新目录**,并保持 API 兼容性(以便 from util import foo 仍然有效),我将其称为 util/。 我可以像这样将 util.py 移动到 util/ 中,

util/
  __init__.py
  util.py
  db.py

并在 util/__init__.py 中这样做

from util import *

,但这是多余的。 我们可以将 util.py 内容放入 __init__.py 中,而不是使用 util/util.py 文件,用户现在可以

from util import foo
from util.db import check_schema

我认为这很好地突出了 util 包的 __init__.py 的作用与 util 模块类似的方式

* 这在其他答案中有所暗示,但我想在这里强调它
** 缺少采用进口体操。 请注意,创建与文件同名的新包将不起作用,请参阅

One thing __init__.py allows is converting a module to a package without breaking the API or creating extraneous nested namespaces or private modules*. This helps when I want to extend a namespace.

If I have a file util.py containing

def foo():
    ...

then users will access foo with

from util import foo

If I then want to add utility functions for database interaction, and I want them to have their own namespace under util, I'll need a new directory**, and to keep API compatibility (so that from util import foo still works), I'll call it util/. I could move util.py into util/ like so,

util/
  __init__.py
  util.py
  db.py

and in util/__init__.py do

from util import *

but this is redundant. Instead of having a util/util.py file, we can just put the util.py contents in __init__.py and the user can now

from util import foo
from util.db import check_schema

I think this nicely highlights how a util package's __init__.py acts in a similar way to a util module

* this is hinted at in the other answers, but I want to highlight it here
** short of employing import gymnastics. Note it won't work to create a new package with the same name as the file, see this

原来是傀儡 2024-07-20 02:30:32

__init__.py :它是在包目录中找到的Python文件,当导入包或包中的模块时调用它。 您可以使用它来执行包初始化代码,即每当导入包时,都会先执行 python 语句,然后再执行该文件夹中的其他模块。 它类似于c或Java程序的main函数,但它存在于Python包模块(文件夹)中而不是核心Python文件中。
当模块导入到 Python 文件中时,它还可以访问此 __init__.py 文件中定义的全局变量。

例如。
我在名为 pymodlib 的文件夹中有一个 __init__.py 文件,该文件包含以下语句:

print(f'Invoking __init__.py for {__name__}')
pystructures = ['for_loop', 'while__loop', 'ifCondition']

当我在解决方案中导入此包 pymodlib 时模块或笔记本或 python 控制台:
这两条语句在导入时执行。
因此,在日志或控制台中,您将看到以下输出:

>>> import pymodlib
Invoking __init__.py for pymodlib

在 python 控制台的下一个语句中: 我可以访问全局变量:

>> pymodlib.pystructures

它给出以下输出:

['for_loop', 'while__loop', 'ifCondition']

现在,从 Python 3.3 开始,可以选择使用此文件文件夹 Python 模块。 所以你可以跳过将其包含在 python 模块文件夹中。

__init__.py : It is a Python file found in a package directory, it is invoked when the package or a module in the package is imported. You can use this to execute package initialization code, i.e. whenever the package is imported the python statements are executed first before the other modules in this folder gets executed. It is similar to main function of c or Java program, but this exists in the Python package module (folder) rather than in the core Python file.
also it has access to global variables defined in this __init__.py file as when the module is imported into Python file.

for eg.
I have a __init__.py file in a folder called pymodlib, this file contains the following statements:

print(f'Invoking __init__.py for {__name__}')
pystructures = ['for_loop', 'while__loop', 'ifCondition']

When I import this package pymodlib in my solution module or notebook or python console:
These two statements get executed while importing.
So in the log or console you would see the following output:

>>> import pymodlib
Invoking __init__.py for pymodlib

in the next statement of python console: I can access the global variable:

>> pymodlib.pystructures

it gives the following output:

['for_loop', 'while__loop', 'ifCondition']

Now, from Python 3.3 onwards the use of this file has been optional to make folder a Python module. So you can skip from including it in the python module folder.

夜夜流光相皎洁 2024-07-20 02:30:32

如果您使用的是 Python 2 并且想要加载文件的同级文件,您只需将文件的父文件夹添加到会话的系统路径中即可。 其行为与当前文件是 init 文件大致相同。

import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)

之后,相对于文件目录的常规导入将正常工作。 例如,

import cheese
from vehicle_parts import *
# etc.

通常您希望使用适当的 init.py 文件,但是在处理遗留代码时,您可能会陷入 f.ex 的困境。 一个硬编码的库来加载特定的文件,仅此而已。 对于这些情况,这是一种替代方案。

If you're using Python 2 and want to load siblings of your file you can simply add the parent folder of your file to your system paths of the session. It will behave about the same as if your current file was an init file.

import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)

After that regular imports relative to the file's directory will work just fine. E.g.

import cheese
from vehicle_parts import *
# etc.

Generally you want to use a proper init.py file instead though, but when dealing with legacy code you might be stuck with f.ex. a library hard-coded to load a particular file and nothing but. For those cases this is an alternative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文