使用eclipse创建包以及子包
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用eclipse创建包以及子包相关的知识,希望对你有一定的参考价值。
参考技术A 使用eclipse创建包以及子包,是件很容易的事情,但是如果你希望创建的包如下面这种情况恐怕不太容易上图展示出层级的样式,但是我使用的eclipes却没有那样展示,而是以一种并行的方式排列,虽然它们在命名上体现了包含关系,但是我不能确定,后来在网上查找,但苦于这种情况不太好描述,也没有什么明确的结果,我推测上图那种展示情况应该是比较早版本的eclipse的展示情况。
另外一种情况,比如你创建了一个包 com.myhouse.mybed,这时候你想在com.myhouse 这个包下创建一个新的类或者接口文件,你可能会发现当你要创建com.myhouse,这个包的时候,会提示你该包已经存在,其实com.myhouse.mybed这个包就像一个文件夹路径,也就是说创建一个包之后,其父包也都已经存在了。所以,你无需再创建com.myhouse, 而是直接创建类或者接口的时候,修改其存储在的包名为com.myhouse就行了。
Python 只导入一个子包,没有其他子包
【中文标题】Python 只导入一个子包,没有其他子包【英文标题】:Python import one subpackage without others 【发布时间】:2016-01-31 19:54:57 【问题描述】:我有以下包结构
package
__init__.py
sub1
__init__.py
foo.py # Contains class Foo
sub2
__init__.py
bar.py # Contains class Bar
我希望能够只使用import package
并拥有package.Foo
和package.Bar
,即我想让子包对用户透明。
问题是导入 sub2 需要很长时间,而且很多用户根本不关心 sub2 中的内容,只想要 sub1 中的内容。因此,我希望用户能够说import package.sub1
或from package import sub1
只需 导入 sub1 并跳过 sub2 的导入。
我知道我可以通过包含 package/__init__.py
来实现第一部分
from .sub1 import *
from .sub2 import *
并且将package/sub1/__init__.py
设置为from .foo import Foo
,对于sub2 也是如此。但是,即使用户尝试仅导入 package.sub1
,这也将始终导入 sub1 和 sub2。
相应地,我可以通过让package/__init__.py
为空并使用与上面相同的sub1/__init__.py
来实现第二部分。但是,仅仅说import package
不会加载 sub1 或 sub2,因此用户必须显式加载它们,然后引用 package.sub1.Foo
。
理想情况下,一个解决方案在 2.7.10 和 3.5.0 中都适用,但如果两者都不可行,我会接受其中一个。
【问题讨论】:
一个更好的问题是为什么sub2
中有一个模块级别的长时间运行代码
所以,事实上,你的问题是:“我希望 import package.sub1
比 import package
做的事情更少,对吧?没有像提前读取字节码这样的奇怪技巧,我认为这是不可能。import A.B
必须首先import A
。注意docs.python.org/3.6/library/importlib.html 底部(最后一个代码块,第 15 行),import_module
是一个递归函数。但是,您可以轻松拥有第三个子包,package.everything
,这将真正将sub1
和sub2
导入到同一个命名空间中。
@Veky:这确实是我最终所做的(嗯,package.all
,但足够接近)
.all 是我的第一个想法,但我决定反对它,因为它 a) 会引起与 package.__all__
的错误关联,并且 b) 对于你不想鼓励的东西来说有点太短了人们去做(一个有吸引力的麻烦)。
【参考方案1】:
您可以将快捷方式添加到模块的__init__.py
:
package/__init__.py
__all__ = [
... add everything you want to be listed for this module
'Foo',
'Bar',
...
]
from package.sub1.foo import Foo
from package.sub2.bar import Bar
现在你应该可以打电话了:
from package import Bar
【讨论】:
这会在import package
之后启用package.Bar
,但它不处理问题的“延迟导入”部分。【参考方案2】:
LazyLoader
类正是针对这种情况提供的:在实际使用模块时推迟加载模块,而不是在导入时。
要构建一个惰性加载器,您可以按照文档中的示例进行操作:
suffixes = importlib.machinery.SOURCE_SUFFIXES
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)])
然后您可以使用finder.find_spec
获取模块的规格并将结果传递给Loader.create_module
以加载它。
仅对一个模块手动执行此操作有点麻烦。
请注意,搜索“lazy import python”你会发现相当多的解决方案,它们各有优缺点,其中一些在 python2.x 中运行。但是上面的LazyLoader
类是python3.5+中的官方方法
【讨论】:
我无法让它从子包中实际加载内容。如果sub2/__init__.py
有from .bar import Bar
,它返回ImportError: No module named 'package.bar'
如果它使用绝对导入,我得到ValueError: module object for 'package.sub2' substituted in sys.modules during a lazy load
这似乎也只有sub2 下的符号,所以我仍然不得不说package.sub2.Bar
而不仅仅是package.Bar
对于将来看到这个的任何人,如果你(像我一样)不能让惰性加载器工作,我的解决方案是只拥有一个 package.all
(或者 .everything,如果你愿意)导入所有内容,而***包不导入任何内容。有关更多讨论,请参阅有关问题的 cmets以上是关于使用eclipse创建包以及子包的主要内容,如果未能解决你的问题,请参考以下文章