Bri*_*ian 36 python module package
有没有办法将__init__.py
多个文件组织到模块中?
原因:模块比包更容易使用,因为它们没有尽可能多的命名空间层.
通常它会生成一个包,我得到了.问题在于包,'import thepackage'给了我一个空命名空间.然后,用户必须使用"from the package import*"(不赞成)或确切知道包含的内容并手动将其拉出到可用的命名空间中.
我想要的是用户"导入包"并拥有看起来像这样的干净名称空间,公开与项目相关的函数和类以供使用.
current_module
\
doit_tools/
\
- (class) _hidden_resource_pool
- (class) JobInfo
- (class) CachedLookup
- (class) ThreadedWorker
- (Fn) util_a
- (Fn) util_b
- (Fn) gather_stuff
- (Fn) analyze_stuff
Run Code Online (Sandbox Code Playgroud)
维护者的工作是避免在不同的文件中定义相同的名称,这在项目像我的一样小时应该很容易.
如果人们可以做from doit_stuff import JobInfo
并让它检索类,而不是包含该类的模块,那也是很好的.
如果我的所有代码都在一个巨大的文件中,这很容易,但我喜欢在事情变得越来越重要时组织起来.我在磁盘上看到的有点像这样:
place_in_my_python_path/
doit_tools/
__init__.py
JobInfo.py
- class JobInfo:
NetworkAccessors.py
- class _hidden_resource_pool:
- class CachedLookup:
- class ThreadedWorker:
utility_functions.py
- def util_a()
- def util_b()
data_functions.py
- def gather_stuff()
- def analyze_stuff()
Run Code Online (Sandbox Code Playgroud)
我只将它们分开,所以我的文件不是很庞大且无法通知.它们都是相关的,尽管有人(可能是我)可能想要自己使用这些类而不导入所有内容.
我已经在各种主题中阅读了一些建议,以下是我可以找到的关于如何执行此操作的每个建议:
如果我不使用__init__.py
,我无法导入任何东西,因为Python不会从sys.path下载到该文件夹中.
如果我使用空白__init__.py
,当import doit_tools
它是一个没有任何内容的空命名空间时.我的文件都没有导入,这使得它更难以使用.
如果我列出了子模块__all__
,我可以使用(皱眉?)from thing import *
语法,但我的所有类都在不必要的命名空间障碍后面.用户必须(1)知道他们应该使用from x import *
而不是import x
(2)手动重新洗牌,直到他们能够合理地服从线宽样式约束.
如果我添加from thatfile import X
语句__init__.py
,我会更接近,但我有命名空间冲突(?)和额外的命名空间,我不想在那里.在下面的示例中,您将看到:
<class 'doit_tools.JobInfo.JobInfo'>
.(doit_tools.JobInfo是一个类,但doit_tools.JobInfo.JobInfo是同一个类......这很纠结,看起来非常糟糕,但似乎没有破坏任何东西.).
current_module
\
doit_tools/
\
- (module) JobInfo
\
- (class) JobInfo
- (class) JobInfo
- (module) NetworkAccessors
\
- (class) CachedLookup
- (class) ThreadedWorker
- (class) CachedLookup
- (class) ThreadedWorker
- (module) utility_functions
\
- (Fn) util_a
- (Fn) util_b
- (Fn) util_a
- (Fn) util_b
- (module) data_functions
\
- (Fn) gather_stuff
- (Fn) analyze_stuff
- (Fn) gather_stuff
- (Fn) analyze_stuff
Run Code Online (Sandbox Code Playgroud)
另外,只是导入数据抽象类的人会得到与他们从'doit_tools导入JobInfo'时所做的不同的东西:
current_namespace
\
JobInfo (module)
\
-JobInfo (class)
instead of:
current_namespace
\
- JobInfo (class)
Run Code Online (Sandbox Code Playgroud)
那么,这只是组织Python代码的错误方法吗?如果没有,分割相关代码但仍然以模块方式收集它的正确方法是什么?
也许最好的情况是,对于使用该软件包的人来说,"从doit_tools导入JobInfo"进行操作会有点困惑吗?
也许是一个名为'api'的python文件,以便使用该代码的人执行以下操作?:
import doit_tools.api
from doit_tools.api import JobInfo
Run Code Online (Sandbox Code Playgroud)
============================================
回应评论的例子:
在python路径中的文件夹'foo'中取以下包内容.
foo/__init__.py
__all__ = ['doit','dataholder','getSomeStuff','hold_more_data','SpecialCase']
from another_class import doit
from another_class import dataholder
from descriptive_name import getSomeStuff
from descriptive_name import hold_more_data
from specialcase import SpecialCase
Run Code Online (Sandbox Code Playgroud)
foo/specialcase.py
class SpecialCase:
pass
Run Code Online (Sandbox Code Playgroud)
foo/more.py
def getSomeStuff():
pass
class hold_more_data(object):
pass
Run Code Online (Sandbox Code Playgroud)
foo/stuff.py
def doit():
print "I'm a function."
class dataholder(object):
pass
Run Code Online (Sandbox Code Playgroud)
做这个:
>>> import foo
>>> for thing in dir(foo): print thing
...
SpecialCase
__builtins__
__doc__
__file__
__name__
__package__
__path__
another_class
dataholder
descriptive_name
doit
getSomeStuff
hold_more_data
specialcase
Run Code Online (Sandbox Code Playgroud)
another_class
并且descriptive_name
有些混乱,并且在命名空间下面还有例如doit()的额外副本.
如果我在一个名为Data.py的文件中有一个名为Data的类,当我从'数据导入数据'执行时,我得到一个命名空间冲突,因为Data是当前命名空间中的一个类,在模块Data中,不知何故也在当前命名空间 (但Python似乎能够解决这个问题.)
Bre*_*arn 14
你可以这样做,但这并不是一个好主意,你正在与Python模块/包的工作方式作斗争.通过导入适当的名称,__init__.py
可以在包命名空间中访问它们.通过删除模块名称,您可以使它们无法访问.(为什么你需要删除它们,请看这个问题).所以你可以用这样的东西接近你想要的东西(in __init__.py
):
from another_class import doit
from another_class import dataholder
from descriptive_name import getSomeStuff
from descriptive_name import hold_more_data
del another_class, descriptive_name
__all__ = ['doit', 'dataholder', 'getSomeStuff', 'hold_more_data']
Run Code Online (Sandbox Code Playgroud)
但是,这将打破后续尝试import package.another_class
.一般情况下,你不能从一个输入任何东西package.module
不做package.module
访问作为导入的参考该模块(虽然与__all__
您可以阻止from package import module
).
更一般地说,通过按类/函数拆分代码,您正在使用Python包/模块系统.Python模块通常应包含您要作为一个单元导入的内容.为方便起见,直接在顶级包命名空间中导入子模块组件并不罕见,但反过来 - 试图隐藏子模块并允许仅通过顶级包命名空间访问其内容- 将导致问题.此外,尝试"清理"模块的包命名空间没有任何好处.那些模块应该在包名称空间中; 这就是他们所属的地方.
归档时间: |
|
查看次数: |
23837 次 |
最近记录: |