我一直在尝试理解在Python中如何导入包和子包。根据我对realpython.com的理解,包只是一个包含python模块和__init__.py
文件的目录,其中可以包含一个__all__
列表对象,其中包含如果使用import *
语句要导入的所有对象。最重要的是,如果您想包含更多的子包,每个子包都应该是一个包含__init__.py
文件的子目录。
那么,让我们假设我正在做一个项目,看起来像这样,其中my_pckg/
是我试图创建的一个包。
Project/
├── main.py
└── my_pckg/
├── __init__.py
├── functions.py
└── abc/
├── __init__.py
└── A.py
我的理解是,如果我想使用functions
模块中的func_1()
函数,我必须运行以下任何一个:
import my_pckg.functions as pckg_fun
pckg_fun.func_1()
from my_pckg.functions import func_1
func_1()
同样,如果我想从abc
子包的A
模块导入函数func_A()
,我所要做的就是使用以下任何一个选项:
import my_pckg.abc.A as pckg_A
pckg_A.func_A()
from my_pckg.abc.A import func_A
func_A()
现在,当我使用Numpy等Python库并且我想使用随机子包中的randn()
函数时,例如,我可以简单地执行
import numpy as np
np.random.randn(2)
然而如果我运行下面的代码片段
import my_pckg as mp
mp.functions.func_1()
或
import my_pckg as mp
mp.abc.A.func_A()
我得到一个像这样的错误:
>>> mp.functions.func_1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'my_pckg' has no attribute 'functions'
或者这个
>>> mp.abc.A.func_A()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'my_pckg' has no attribute 'abc'
所以,我猜要么有更多的创建模块,我认为,或者我不理解像NumPy这样的模块是如何实际工作的。
最后,Mitch Hedberg的这个笑话真实地总结了我对这一切的感受:
他们说雪碧的配方是柠檬和酸橙,但我试着在家里做,还有更多的东西。[…]
在__init__.py
中添加您想要从该模块中使用的东西的import语句,当您只导入该模块时
使用您的示例,在my_pckg/__init__.py
中,您将拥有
import functions
import abc.A
在那之后,你应该能够做你所描述的没有任何问题。
编辑:在包内导入的最佳实践略有不同。即使模块在同一文件夹中,您也应该像这样从.
导入模块,而不是直接导入:
from . import functions
from abc import A
第二行的副作用是您将直接调用mp.A.func_A()
而不是mp.abc.A.func_A()
如果程序中的任何代码 都导入了该子模块,那么包子模块可以作为其包的属性使用。当您第一次使用import numpy
时,NumPy自己导入了自己的子模块,让您无需显式导入这些子模块即可访问它们:from . import linalg
from . import fft
from . import polynomial
from . import random
from . import ctypeslib
from . import ma