2015-08-22 115 views
11

我是Python新手,但仍然无法理解为什么我们需要使用__init__.py文件导入模块。我已经通过其他问题和答案,如thisPython - 为什么我可以导入没有__init__.py的模块?

什么让我困惑的是,我可以导入我的模块没有__init__py,所以为什么我需要它在所有

我的例子,

index.py 
    modules/ 
     hello/ 
      hello.py 
      HelloWorld.py 

index.py,

import os 
import sys 

root = os.path.dirname(__file__) 
sys.path.append(root + "/modules/hello") 

# IMPORTS MODULES 
from hello import hello 
from HelloWorld import HelloWorld 

def application(environ, start_response): 

    results = [] 

    results.append(hello()) 

    helloWorld = HelloWorld() 
    results.append(helloWorld.sayHello()) 

    output = "<br/>".join(results) 

    response_body = output 

    status = '200 OK' 

    response_headers = [('Content-Type', 'text/html'), 
         ('Content-Length', str(len(response_body)))] 

    start_response(status, response_headers) 

    return [response_body] 

模块/你好/ hello.py,

def hello(): 
    return 'Hello World from hello.py!' 

模块/你好/ HelloWorld.py,

# define a class 
class HelloWorld: 
    def __init__(self): 
     self.message = 'Hello World from HelloWorld.py!' 

    def sayHello(self): 
     return self.message 

结果,

Hello World from hello.py! 
Hello World from HelloWorld.py! 

什么需要就是这两条线,

root = os.path.dirname(__file__) 
sys.path.append(root + "/modules/hello") 

没有任何的__init__py。有人可以解释为什么它以这种方式工作吗?

如果__init__py是正确的方法,我该怎么做/更改我的代码?

回答

1

我认为这是一个很好的'answer'因为我不明白。

myMath/ 
    __init__.py 
    adv/ 
     __init__.py 
     sqrt.py 
     fib.py 
    add.py 
    subtract.py 
    multiply.py 
    divide.py 

MYMATH/__ init__.py

from add import add 
from divide import division 
from multiply import multiply 
from subtract import subtract 
from adv.fib import fibonacci 
from adv.sqrt import squareroot 

index.py

import sys 

sys.path.append('C:\Users\mdriscoll\Documents') 

import mymath 

print mymath.add(4,5) 
print mymath.division(4, 2) 
print mymath.multiply(10, 5) 
print mymath.fibonacci(8) 
print mymath.squareroot(48) 
9

__init__.py适用于包装。一个软件包包含一系列相关模块。如果您只需要使用一个模块,则不需要使用__init__.py;只需将单个.py文件放在系统路径的某个位置,然后就可以导入它。

软件包的目的不仅仅是让你导入它们中的模块。这是将模块分组在一起。这样做的主要好处是,如果模块位于包中,那么该模块可以使用相对导入从包导入其他模块。如果您在同一个包中有foo.pybar.py,那么foo只能做from . import bar。这样,如果重新构建包或更改其名称,则可以使包内导入更加紧凑,并且更易于重新组织。

此外,一个明显的好处是。 。 。如果你把它做成一个包,你不需要每次你想从中导入东西时都要这样做。

+0

包的另一大优势是分离的命名空间下降。如果你编写你自己的'json'模块,它将会影响全局'json'模块。但是如果你将其设置为'mypackage.json',它不会导致这样的冲突(至少在Python 3或Python 2中,from __future__ import absolute_import')。 – Blckknght

+0

谢谢。你能给我看一个需要'__init __。py'的包的例子吗?谢谢。 – laukok

+4

@teelou:在3.3版之前的Python版本中,所有包都被* required *为'__init __。py'文件。 Python 3.3删除了这个要求,参见[PEP 420](https://www.python.org/dev/peps/pep-0420/)。听起来你可能对包还不是很了解,所以在阅读PEP之前,你可能想阅读[Python文档的适当部分](https://docs.python.org/2/tutorial/modules.html #packages)首先。 – Blckknght

2

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

modules/hello/__init__.py 
modules/hello/module.py 

modules是在你的路径,你可以在module.py导入代码

import spam.module 

from spam import module 

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

__init__.py文件通常为空,但可用于以更方便的名称导出包的选定部分,保留便利函数等。给定上述示例,init模块的内容可通过

import spam 

最后这里是官方文档有说这个文件:

__init__.py文件都需要使Python视该 目录为一个包;这样做的目的是为了防止 具有通用名称的目录(如 的字符串)无意中隐藏了稍后在 模块搜索路径中发生的有效模块。在最简单的情况下,__init__.py可以只是 是一个空文件,但它也可以为包执行初始化代码 或设置__all__变量,稍后介绍。

+0

'mydir/spam/__init__.py mydir/spam/module.py'与我的例子中的modules/hello/hello.py'不一样吗? – laukok

+0

不,@ teelou,他们不是相同的字符串。但他们是相似的。它是一个抽象的例子来帮助概念的概括。但是我编辑了这个文件,以使抽象消失并减轻负担。祝你好运。 –

+0

你在哪里使用'import spam.module'?入口点在哪里 - 比如index.py? – laukok

4

我认为这可能是由于Python版本所使用。我做了一些实验,并发现了其结构如下:

import packages.file as p 
p.fun() 

和file.py的内容:main.py的

[email protected] ~/temp $ tree . 
. 
├── main.py 
└── packages 
    ├── file.py 
    └── file.pyc 

1 directory, 5 files 

内容

import sys 
def fun(): 
    print(sys.path) 

当我执行main.py使用Python 2.7.12我得到ImportError,而使用Python 3.5.2执行main.py只是起作用。

在packages目录中添加__init__.py后,代码可以在两个版本的Python中使用。

+0

感谢您的回答! – laukok

2

基于this链接:自Python 3以来。3

允许隐命名包是指提供一个__init__.py文件的要求,可以完全

相关问题