__init__.py的作用是什么?

问题:__init__.py的作用是什么?

什么是__init__.py一个Python源目录?

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


回答 0

它曾经是软件包的必需部分(旧的3.3之前的“常规软件包”,而不是新的3.3+“命名空间软件包”)。

这是文档。

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.


回答 1

命名__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

based on this


回答 2

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

一个例子

这是我的一个项目的示例,在该项目中,我经常导入sessionmaker被叫Session以与数据库交互。我写了一个带有一些模块的“数据库”包:

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在这里定义,就可以使用以下语法开始新的会话。此代码将从“数据库”包目录的内部或外部执行相同。

from database import Session
session = Session()

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

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.


回答 3

有两个主要原因 __init__.py

  1. 为方便起见:其他用户将不需要知道您的函数在包层次结构中的确切位置。

    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

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

    from your_package import add

    不知道file1,例如

    from your_package.file1 import add
  2. 如果您想初始化一些东西;例如,日志记录(应放在顶层):

    import 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.

    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, 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)
    

回答 4

__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.


回答 5

从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/
是__init__。 py对于Python 3中的软件包不是必需的?

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?


回答 6

在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称为函数。我们可以__init__.py像这样在subPackage_b中使用:

__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.


回答 7

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

它指定应将程序包视为模块,因此将其包括在内(即使它为空)。

在某些情况下,您实际上可能会使用__init__.py文件:

假设您具有以下文件结构:

main_methods 
    |- methods.py

methods.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__.pyfoo()只需导入即可使用main_methods

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

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


一些Python软件包实际上是这样做的。以JSON为例,其中running import json实际上是__init__.pyjson包中导入的(请参阅此处的包文件结构):

源代码: Lib/json/__init__.py

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

It specifies a package should be treated as a module, 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


回答 8

__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
>>> 

回答 9

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

root\
    stuff\
         other.py

    morestuff\
         another.py

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

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.


回答 10

一个__init__.py文件使得进口容易。当__init__.py包中包含an时,a()可以从文件中导入函数,b.py如下所示:

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