【发布时间】:2015-08-20 19:23:05
【问题描述】:
我在 Mac OSX 上使用 Python 3.4.2,我有一个简单的版本控制 Python 项目,其目录/文件结构如下所示:
vcs_projectname/
foo/
__init__.py
simplefunc.py
docs/
other_related_stuff/
__init__.py 文件如下所示:
from .simplefunc import helloworld
__all__ = ['helloworld'] # Not sure whether I really need this line...?
simplefunc.py 文件如下所示:
def helloworld():
print('Hello world!')
我通过更改到项目层次结构之外的目录来测试我的代码,将我的 PYTHONPATH 环境变量(在 bash 中)设置为指向 vcs_projectname 基本目录,然后启动 ipython:
> cd ~
> export PYTHONPATH=~/vcs_projectname
> ipython
在 ipython 中,我导入包 foo,然后查看其目录结构,结果如下:
In [1]: import foo
In [2]: dir(foo)
Out[2]:
['__all__',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__path__',
'__spec__',
'helloworld',
'simplefunc']
我的问题:如何去掉包目录结构中对simplefunc文件模块的引用?这是可取的,因为在最好的情况下,它只是无用的混乱(我们不需要它,因为我们真正想要的东西,helloworld() 函数,已经在包级别由@987654334 提供@file),在最坏的情况下,它本质上是对不相关的实现细节(项目的底层文件结构)的引用,以后可能会改变,因此我不希望我的用户期待和依赖未来的版本。
【问题讨论】:
-
您可以
delete 参考。但我不会。 -
好的,我只是在导入实际完成后在 ipython 命令行
In [3]: del(foo.simplefunc)上尝试过,从技术上讲它确实有效,但肯定有比这更优雅的解决方案吗?难道没有其他方法可以让我构建__init__.py文件本身以达到相同的结果,这不仅仅是一个丑陋的组合或解决方法吗? -
问题是,你想要完成的最终目标是一个丑陋的组合(在我看来)。您将对用户隐藏源代码结构,这会使调试变得比需要的更难并且非常令人沮丧。使用
_underscore前缀和 文档 来明确代码的哪些部分是包的公共 API 的一部分,哪些不是。 -
好的,所以,要明确一点,您建议的解决方案本质上是,如果我想这样做,那么我应该考虑将
simplefunc.py文件重命名为_simplefunc.py以保留底层源代码文件结构暴露,但仍向用户表明它不打算成为公共 API 的一部分?我是否正确地描述了你的立场? -
是的,这就是我的意思,这是清楚地表明您将此模块(名称/位置)视为内部细节的明显方式。但这通常甚至没有必要:如果您在某个时候确实更改了代码布局并移动模块、合并它们等,您始终可以添加内部向后兼容性导入以确保代码适用于直接使用您的“内部”模块的用户仍然可以使用。查看example of that in
sqlalchemy
标签: python python-3.x import package python-import