__init__.py ::在顶级导入时使子模块例程可用

时间:2016-06-15 02:51:45

标签: python import initialization package

假设以下结构......

root/test.py
root/myapp/__init__.py
root/myapp/myapp.py       # contains My_App_Class()
root/myapp/SomeObject.py  # contains My_Obj_Class()

如果我的__init__.py包含以下结构:

from myapp import *
import SomeObject

__all__ = ['SomeObject']

我希望能够拨打myapp并从myapp/myapp.py预先提取例程,以便我可以在test.py中执行以下操作:

import myapp

if 'My_App_Class' in myapp.__dict__.keys():
    print 'success'
else:
    print 'fail'

if 'My_Obj_Class' in myapp.SomeObject.__dict__.keys():
    print 'success'
else:
    print 'fail'

这样我就可以有效地将from myapp.myapp import *折叠为from myapp import *

In [1]: %run test.py
fail
success

1 个答案:

答案 0 :(得分:2)

yur __all__文件中的__init__.py属性阻止了其他名称(从myapp / myapp.py导入)在使用myapp包时显示。

只是不要使用all - 也许,为避免歧义,请将导入更改为:

from myapp import *

from .myapp import *

换句话说,您的__init__.py文件应该只是:

from .myapp import *
import SomeObject

并没有其他行。

另一方面,test.py如果进一步不正确 - 如果它以import myapp开头,则所有myapp / myapp.py的名称都将位于myapp名称空间中。当你在问题中进一步说明时,你应该将第一行改为from myapp import *

强制性说明:您应该避免在从项目包导入名称的Python项目中执行import *和variantes。 Python程序和项目应该 始终从包/模块中导入单个名称 - 使用明确写入的名称,任何阅读代码的人都会确切地知道您使用的每个函数或类来自何处。此外,IDE和其他编程工具将能够检查不存在或不一致的名称并警告您。

但是,请注意,可以在程序包from module import *中使用__init__.py,以便将每个程序包模块中的名称(在__all__导出中)公开到程序包名称空间本身 - 这就是你想要的。