仅使模块中的特定符号可导入,f.i。用`__all__`
Make only specific symbols in a module importable, f.i. with `__all__`
tl;博士:
我喜欢干净的 APIs,因此我不喜欢在模块 API 中出现“内部”导入,例如 import numpy as np
在我的模块中。 =46=]
在我的包中(可使用 setup.py 安装)我有几个子模块,每个子模块导入一组模块,f.i。 numpy
或 sys
.
等内置函数
假设在我的包 mytools
中,我有一个子模块 mytools.mysubtools
,我在其中定义了一个函数 foo
,它需要 numpy
(使用 import numpy as np
导入)。 foo
添加到 __all__ = ['foo']
.
现在我用 import mytools.mysubtools as mst
导入这个子模块。使用代码完成访问 mst
时(例如使用 Spyder IDE、PyCharm、Kite...)等,它总是显示 all符号 和 在 mst
中导入,在本例中为 foo
和 np
.
我可以避免像 np
这样的导入出现在导入的模块中,这样只有 foo
出现吗?
详细说明
假设我的包结构如下所示:
/mytools/
|-- __init__.py # "mytools-init"
|-- my_subtools.py
|-- some_other_subtools.py
__init__.py
文件如下所示:
from . import my_subtools as mysubtools
__all__ = ['mysubtools']
和my_subtools.py
:
import numpy as np
__all__ = ['foo']
def foo():
return np.sqrt(4**3)
现在我用
导入my_subtools
import mytools.mysubtools as mst
使用导入模块时,代码补全等总是显示np
和foo
、f.i。输入 mst.
时。对于较大的模块,有许多导入 and/or function/class 定义,这使得使用代码补全变得非常困难,因为对 API 的简单检查显示 all 导入的模块和所有定义。
使用 __all__
可以避免为 wild/star 导入所有符号,例如 from mytools.mysubtools import *
。 __all__
也能以某种方式用于破坏显式导入吗?
或者有什么推荐的方法可以避免导入模块的所有符号吗?
对于函数,我使用 name mangling、f.i。 def _baz(): return 4**4
.
但这也对进口、f.i是可取的吗? import numpy as _np
?有什么缺点吗?
我在找什么:
显式解决方案,因为:显式优于隐式。
例如 __all__
,但用于显式导入。或者像 __except__ = ['np']
这样的东西,它从导入中排除符号。
__all__ = [...]
是“可导出”名称的一个很好的提示,但这只是一个提示。 (尽管 PyCharm 等一些 IDE 确实倾向于获得线索。)
我肯定不会import numpy as _np
;你只会让你的生活更艰难。
你不能阻止别人从你的模块中导入东西,如果他们在那里......如果你真的真的想要,你当然可以后缀所有你的模块有像 del np, sys, os, quux, bar
这样的咒语;那样的话那些名字就不会被导入了,但是...我真的不认为这是值得的。
感谢@chepner 的评论,我一直在研究 python 标准库中的链接实现。
结论是,标准库中经常使用导入模块的名称修饰。在我看来,这是一个非常明显的迹象,这被认为是 pythonic and/or 没有严重的缺点。
可以找到几个 name-mangling 导入的例子,f.i.:
哪些模块是 name-mangled 似乎因文件而异。似乎越是“system-relevant”的模块,越不容易被name mangled。例如导入
import re as _re
import math as _math
经常被名称损坏,而 import os as _os
则不那么常见。这只是我的印象,所以不一定是真的。
tl;博士:
我喜欢干净的 APIs,因此我不喜欢在模块 API 中出现“内部”导入,例如 import numpy as np
在我的模块中。 =46=]
在我的包中(可使用 setup.py 安装)我有几个子模块,每个子模块导入一组模块,f.i。 numpy
或 sys
.
等内置函数
假设在我的包 mytools
中,我有一个子模块 mytools.mysubtools
,我在其中定义了一个函数 foo
,它需要 numpy
(使用 import numpy as np
导入)。 foo
添加到 __all__ = ['foo']
.
现在我用 import mytools.mysubtools as mst
导入这个子模块。使用代码完成访问 mst
时(例如使用 Spyder IDE、PyCharm、Kite...)等,它总是显示 all符号 和 在 mst
中导入,在本例中为 foo
和 np
.
我可以避免像 np
这样的导入出现在导入的模块中,这样只有 foo
出现吗?
详细说明
假设我的包结构如下所示:
/mytools/
|-- __init__.py # "mytools-init"
|-- my_subtools.py
|-- some_other_subtools.py
__init__.py
文件如下所示:
from . import my_subtools as mysubtools
__all__ = ['mysubtools']
和my_subtools.py
:
import numpy as np
__all__ = ['foo']
def foo():
return np.sqrt(4**3)
现在我用
导入my_subtools
import mytools.mysubtools as mst
使用导入模块时,代码补全等总是显示np
和foo
、f.i。输入 mst.
时。对于较大的模块,有许多导入 and/or function/class 定义,这使得使用代码补全变得非常困难,因为对 API 的简单检查显示 all 导入的模块和所有定义。
使用 __all__
可以避免为 wild/star 导入所有符号,例如 from mytools.mysubtools import *
。 __all__
也能以某种方式用于破坏显式导入吗?
或者有什么推荐的方法可以避免导入模块的所有符号吗?
对于函数,我使用 name mangling、f.i。 def _baz(): return 4**4
.
但这也对进口、f.i是可取的吗? import numpy as _np
?有什么缺点吗?
我在找什么:
显式解决方案,因为:显式优于隐式。
例如 __all__
,但用于显式导入。或者像 __except__ = ['np']
这样的东西,它从导入中排除符号。
__all__ = [...]
是“可导出”名称的一个很好的提示,但这只是一个提示。 (尽管 PyCharm 等一些 IDE 确实倾向于获得线索。)
我肯定不会import numpy as _np
;你只会让你的生活更艰难。
你不能阻止别人从你的模块中导入东西,如果他们在那里......如果你真的真的想要,你当然可以后缀所有你的模块有像 del np, sys, os, quux, bar
这样的咒语;那样的话那些名字就不会被导入了,但是...我真的不认为这是值得的。
感谢@chepner 的评论,我一直在研究 python 标准库中的链接实现。
结论是,标准库中经常使用导入模块的名称修饰。在我看来,这是一个非常明显的迹象,这被认为是 pythonic and/or 没有严重的缺点。
可以找到几个 name-mangling 导入的例子,f.i.:
哪些模块是 name-mangled 似乎因文件而异。似乎越是“system-relevant”的模块,越不容易被name mangled。例如导入
import re as _re
import math as _math
经常被名称损坏,而 import os as _os
则不那么常见。这只是我的印象,所以不一定是真的。