禁止出现在命名空间w / __init__.py中的子模块

时间:2014-09-21 21:44:19

标签: python package

如何避免类/方法/等的多个位置。在python包的命名空间内?考虑具有以下目录结构和代码的包:

dummyproj/
├── __init__.py
└── main.py

# main.py
# =======
def dummy_func():
    print "hello world"

# __init__.py
# ===========
from main import *

通过这种结构,函数dummy_func可以从包中获得。但是,它也可以从名为main的子模块中获得。例如:

>>> import dummyproj
>>> dir(dummyproj)
['__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 '__path__',
 'dummy_func',
 'main']
>>> dummyproj.dummy_func()
hello world
>>> dummyproj.main.dummy_func()
hello world

如何阻止main显示在dummy_proj命名空间中?我的理解是,在dummy_func中包含__init__.py的代码是不好的形式。

3 个答案:

答案 0 :(得分:1)

你不能(以干净和普遍接受的方式)。

但问题是,你为什么要这样做?理想情况下,您图书馆的用户会使用您的文档来了解您的图书馆的API,并且不必使用dir()

如果我正在调试您的库,如果使用dir()我可能会这样做,我就不想让库的结构与我混淆了。

因此,只需按照您在示例中的方式构建软件包是完全可以接受的,大多数库都是以这种方式构建的:

  • 使用子模块/包(可能是它们的几个层次)以合理的方式构造代码
  • 然后在常用函数/类/等的顶级包中提供便利导入。

一个很好的例子是requests模块:

import requests
requests.get(url)

get()功能以convenience import at the top-level package形式提供,并且也以此方式记录(quickstart docs | API docs)。但get()函数实际上存在于requests.api.get


另一个很好的例子是SQLAlchemy,它甚至使用了几个便利导入级别:

Column课程位于sqlalchemy.sql.schema.Column。但它作为sqlalchemy.schema.Column的便利导入提供,甚至在sqlalchemy.Column的顶部也是如此。 (尽管sqlalchemy.schema命名空间只是出于兼容性原因,据我所知)。

答案 1 :(得分:0)

没有简单的方法可以做到这一点。 (至少我知道)

您可以使用del进行清理,也可以使用函数为您生成模块。这样的事情:(在__init__.py)。

def __init__mod():
    from main import dummy_func

    g = globals()
    g['dummy_func'] = dummy_func

__init__mod()

答案 2 :(得分:0)

只需在__init__.py文件中删除它:

# __init__.py
# ===========
from main import *
del main