隐藏模块中的模块导入

时间:2014-10-22 20:21:08

标签: python

我有一个包含一些依赖项的小包,例如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()

如何在程序包导入中隐藏各种模块的导入?

2 个答案:

答案 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模块工作方式的副作用。您导入模块的任何内容都将作为该模块中的顶级对象提供。大多数人并不担心它,只是使用规范的导入路径。