繁体   English   中英

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

[英]Suppress submodules from appearing in namespace w/ __init__.py

如何避免类/方法/等的多个位置。 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名称空间中? 我的理解是,在__init__.py包含dummy_func的代码将是一种不好的形式。

您不能(以一种干净且普遍接受的方式)。

但是问题是,为什么要这么做? 理想情况下,您的库的用户可以使用您的文档来了解库的API,而不必诉诸使用dir()

而且,如果我正在调试您的库dir()如果使用dir() ,则可能正在执行此操作dir() ,那么我就不会希望混淆我的库结构。

因此,仅按照示例中的方式构建程序包是完全可以接受的,大多数库都是以这种方式构建的:

  • 使用子模块/程序包(可能包括多个级别)以合理的方式构造代码
  • 然后在顶级软件包中为常用的函数/类/等提供方便的导入。

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

import requests
requests.get(url)

get()函数是为方便导入而在顶级软件包中提供的 ,并且也以这种方式进行了记录( quickstart docs | API docs )。 但是get()函数实际上存在于requests.api.get


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

Column类位于sqlalchemy.sql.schema.Column 但是,它是作为方便导入提供的sqlalchemy.schema.Column ,甚至在最顶层也提供了sqlalchemy.Column (据我所知,尽管sqlalchemy.schema名称空间只是出于兼容性原因)。

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

您可以只使用del进行清理,也可以使用一个函数来为您生成模块。 像这样:(在__init__.py )。

def __init__mod():
    from main import dummy_func

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

__init__mod()

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM