我有一个包含一些依赖项的小包,例如pandas和gensim。文件结构就像这样
/package
__init__.py
agg_clean.py
在__init__.py
文件中,我有import agg_clean
所以我能够以链式方式访问这些函数,例如:
import package as pkg
pkg.agg_clean.function()
但是,我在agg_clean.py
,(pandas,os等)中有几个import语句。当我如上所述进行链式导入时,我也可以访问agg_clean
中的导入,例如pkg.agg_clean.os.listdir()
如何在程序包导入中隐藏各种模块的导入?
答案 0 :(得分:3)
tl; dr :你不能干净利落。或者更确切地说,你不应该担心这样的事情。
在这种情况下没有namespace collisions
,因为os模块在名称pkg.agg_clean.os
下加载。如果用户想要使用您导入的os包,那么让他们这样做是没有害处的。最重要的是,没有良好的方式阻止他们这样做。
这里有一些有趣的事情需要记住。使用以下可由另一个python脚本导入的python模块:
# module_im_importing.py
import os as _os
__all__ = ["echo"]
name_not_available = 'some_constant_string'
def echo(object):
pass
如果您的用户使用import module_im_importing
导入裸模块,则所有已定义的变量均以module_im_importing
的名称提供给其环境。
>>> import module_im_importing
>>> dir() # Lookup local namespace
['__builtins__', '__doc__', '__name__', '__package__', 'module_im_importing']
>>> dir(module_im_importing) # See defined items in your package.
['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'echo', 'name_not_available', 'os']
如果他们改为from module_im_importing import *
(不鼓励),行为会有所不同:
>>> from module_im_importing import *
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'echo']
这会导致文件module_im_importing.py
中定义的名称导入到用户的本地名称空间中。因为我们在您的模块中使用了__all__
,所以只会将__all__
中定义的项目从模块导入到用户本地命名空间。例如,如果你定义了一个与他们可能正在使用的另一个包冲突的echo
这样的函数,这会污染他们的命名空间。
这就是PEP8中明显不喜欢通配符导入的原因。来自文件:
Wildcard imports (from <module> import *) should be avoided, as they make it unclear which names are present in the namespace, confusing both readers and many automated tools.
无论如何,请不要担心这样的事情。如果您的模块的用户不遵循PEP8,这只是一个问题,并且他们可能应该显示他们的方式的错误。请记住,在Python中,We're all consenting adults here
。
答案 1 :(得分:0)
这实际上只是python模块工作方式的副作用。您导入模块的任何内容都将作为该模块中的顶级对象提供。大多数人并不担心它,只是使用规范的导入路径。