在Python中导入模块和__init__.py

28

我一直在研究__init__.py文件的功能。据说我们需要在包含模块的文件夹中添加一个空的__init__.py文件,以便可以导入这些模块。但是,我尝试将文件夹路径添加到PYTHONPATH(Windows 7中的环境变量)中。尽管这个文件夹中没有__init__.py文件,我仍然可以从该文件夹导入模块。您能解释一下没有__init__.py文件的情况下如何导入这些模块吗?

4个回答

19

__init__.py将一个文件夹转变成一个。这样做可以创建模块层次结构,使得您可以使用如下的导入语句:

import mymodule.cool.stuff

没有使用软件包是不可能做到的。


好的,假设有一个名为"A"的文件夹,并且"A"中有一个__init__.py文件。但是"A"不在PYTHONPATH中。我能从"A"文件夹中导入模块吗?Python会搜索我的计算机上的所有文件夹以知道它们是否有"__init__.py"文件吗?也就是说,Python如何知道"A"的路径? - alwbtc
6
你仍然需要将包的路径添加到你的PYTHONPATH中。Python不会在整个计算机中搜索包含__init__.py的文件夹。 - Björn Pollex

10
如果一个目录(文件夹)包含一个__init__.py文件,那么它就成为一个。你所读到的并不完全正确,正如你发现的那样。包可以像导入模块一样被单独导入,并且会运行__init__.py中的任何代码,尽管通常是空的。包是将多个模块组合在一起的一种方式,您可以使用以下方法加载它们:
import package-name.module-name

Python的包(package)也可以嵌套,而且通常会这样做。在你的Python软件目录下的Lib目录中有很多示例。


9

在模块目录中有或没有__init__.py文件的区别是:

当你__init__.py文件(即使为空),你可以使用以下方式导入模块:

from dirname import MyModule

但是当你完全没有_init_.py文件时,你不能导入模块,除非将该模块的路径添加到PYTHONPATH中。在这种情况下,from dirname import MyModule会失败或报错。

# 没有_init_.py的目录/模块结构

[root@Machine python]# cd NoInitModule/
[root@Machine NoInitModule]# pwd
/python/NoInitModule
[root@Machine NoInitModule]# ls -l
total 4
-rw-r--r--. 1 root root 44 Jan 16 07:02 ModuleX.py

# 带有 _init_.py 的目录/模块的结构

[root@Machine NoInitModule]# cd ../InitModule/
[root@Machine InitModule]# ls -l
total 4
-rw-r--r--. 1 root root  0 Jan 16 07:13 __init__.py
-rw-r--r--. 1 root root 49 Jan 16 07:12 ModuleY.py
[root@Machine InitModule]#

示例:

# 没有 _init_.py,从目录导入模块语句 - 不起作用

[root@Machine python]# cat impomod.py
from NoInitModule import ModuleX

ModuleX.printBye()

[root@Machine python]# python impomod.py
Traceback (most recent call last):
  File "impomod.py", line 7, in <module>
    from NoInitModule import ModuleX
ImportError: No module named NoInitModule
[root@Machine python]#

# 没有 _init_.py,导入语句 - 不起作用

[root@Machine python]# vim impomod.py
[root@Machine python]# cat impomod.py
#from NoInitModule import ModuleX
import ModuleX

ModuleX.printBye()
[root@Machine python]# python impomod.py
Traceback (most recent call last):
  File "impomod.py", line 8, in <module>
    import ModuleX
ImportError: No module named ModuleX
[root@Machine python]#

# 没有 _init_.py,将路径插入PYTHONPATH,在插入路径后导入模块语句 - 可行

[root@Machine python]# vim impomod.py
[root@Machine python]# cat impomod.py
import sys
sys.path.append('/python/NoInitModule')
print sys.path

import ModuleX
ModuleX.printBye()

[root@Machine python]# python impomod.py
Bye from Module X with no __init__.py
[root@Machine python]#

# 在 _init_.py 中,没有插入路径,从 dir 导入模块语句 - 可以工作

[root@Machine python]# cat impXmod.py
import sys
from InitModule import ModuleY
ModuleY.printSeeU()
[root@Machine python]#

[root@Machine python]# python impXmod.py
See you from Module Y having __init__.py

# 拥有 _init_.py,没有路径的 INSERT,导入模块的语句不起作用

[root@Machine python]# vim impXmod.py
[root@Machine python]# cat impXmod.py
import sys
#from InitModule import ModuleY
import ModuleY
ModuleY.printSeeU()

[root@Machine python]# python impXmod.py
Traceback (most recent call last):
  File "impXmod.py", line 3, in <module>
    import ModuleY
ImportError: No module named ModuleY

当然,这里还可以加入关于子文件夹的问题。

6

是的,这个方法可行,正如你所见。空的__init__.py文件的原因是标记子文件夹为包含模块的文件夹。

因此,在PYTHONPATH中的文件夹可以拥有其中的模块,但是这些文件夹的任何子文件夹必须在其中有一个__init__.py文件才能从中导入模块。


1
__init__.py 不一定要为空。 - Ignacio Vazquez-Abrams
@Ignacio:如果它的唯一任务是标记一个文件夹有模块,那么它也不必包含任何内容。OP提到了空的__init__.py文件。 - quamrana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接