Python 是否可以使子包显示为实际的包
开发人员试图使Python 是否可以使子包显示为实际的包,python,packages,python-import,Python,Packages,Python Import,开发人员试图使tensorflow目录显示为实际的包,而实际的包根实际上是tensorflow/python,我对此感到非常失望。通过使用表单的\uuuu init\uuuuu.py文件 from tensorflow.python import * del python 他们试图实现这一目标。这导致在使用软件包时出现一些不一致的行为(至少在我看来是这样),例如 import tensorflow.python # seems to work tensorflow
tensorflow
目录显示为实际的包,而实际的包根实际上是tensorflow/python
,我对此感到非常失望。通过使用表单的\uuuu init\uuuuu.py
文件
from tensorflow.python import *
del python
他们试图实现这一目标。这导致在使用软件包时出现一些不一致的行为(至少在我看来是这样),例如
import tensorflow.python # seems to work
tensorflow.python # AttributeError: no attribute 'python'
from tensorflow.python import Session # works as expected
tensorflow.python.Session # AttributeError: no attribute 'python'
from tensorflow import python # works as expected
tensorflow.nn # works as expected
import tensorflow.nn # ImportError: no module 'tensorflow.nn'
tensorflow.nn.tanh # works as expected
from tensorflow.nn import tanh # ImportError: no module 'tensorflow.nn'
现在,我想知道是否/如何能够避免大部分/所有这些问题,以获得更一致的行为。第一组不一致可以通过不删除python
属性轻松解决。然而,考虑到目标是使整个包看起来像一个子包,这可能并不完全令人满意
为了让事情简单,让我们考虑下面的包结构
package/
__init__.py
api/
__init__.py
code.py
其中package/api/code.py
看起来像
def a():
return 'alpha'
def b():
return 'bravo'
而package/api/\uuuu init\uuuu.py
将是
import package.api.code
是否可以创建package/\uuuuu init\uuuuuu.py
,以实现以下功能
import package.api # ImportError: no module 'package.api'
package.api # AttributeError: no attribute 'api'
from package.api import code # ImportError: no module 'package.api'
package.api.code # AttributeError: no attribute 'api'
from package import api # ImportError: cannot import 'api'
package.code # works as expected
import package.code # works as above
package.code.a # works as expected
from package import a # correctly imports function a
我相信最后四行代码应该通过添加到sys.modules
中得到预期的结果,但我似乎无法找到使import package.api
失败的方法
有人知道如何做到这一点吗?请允许我使用我忽略或应该考虑的案例来实现上述目标。
首先,我必须说我真的讨厌这种“阴暗”的技巧。它会对各种IDE智能感知产生不良影响,并使库结构不易理解。但还是
如果希望子模块code.py充当实际的子包,则需要创建一个虚拟模块:package/
__init__.py
api/
__init__.py
code.py
code/
__init__.py
在代码/\uuuu init\uuuu py中添加以下内容:
from package.api.code import *
在包/_uuinit_uuu.py中:
from package.code import *
import package.api
del package.api
然后,这一部分应按预期工作:
import package.code # works as expected
package.code # works as expected
package.code.a # works as expected
from package import a # works as expected
如果您进一步将其添加到包/\uuuu init\uuuuu.py中:
from package.code import *
import package.api
del package.api
您基本上断开了用户访问package.api的连接,但除此之外,他们仍然可以使用“from x import y”通过子包访问子模块:
import package.api # works
package.api.a() # AttributeError: module 'package' has no attribute 'api'
import package.api.code # works
package.api.code.a() # AttributeError: module 'package' has no attribute 'api'
from package.api import code # works
code.a() # works
from package import api # works
api.code.a() # AttributeError: module 'package.api' has no attribute 'code'
首先,我必须说,我讨厌这种“阴暗”的技术。它会对各种IDE智能感知产生不良影响,并使库结构不易理解。但还是 如果希望子模块code.py充当实际的子包,则需要创建一个虚拟模块:
package/
__init__.py
api/
__init__.py
code.py
code/
__init__.py
在代码/\uuuu init\uuuu py中添加以下内容:
from package.api.code import *
在包/_uuinit_uuu.py中:
from package.code import *
import package.api
del package.api
然后,这一部分应按预期工作:
import package.code # works as expected
package.code # works as expected
package.code.a # works as expected
from package import a # works as expected
如果您进一步将其添加到包/\uuuu init\uuuuu.py中:
from package.code import *
import package.api
del package.api
您基本上断开了用户访问package.api的连接,但除此之外,他们仍然可以使用“from x import y”通过子包访问子模块:
import package.api # works
package.api.a() # AttributeError: module 'package' has no attribute 'api'
import package.api.code # works
package.api.code.a() # AttributeError: module 'package' has no attribute 'api'
from package.api import code # works
code.a() # works
from package import api # works
api.code.a() # AttributeError: module 'package.api' has no attribute 'code'
我设法写了一些几乎可以工作的东西(在
package/\uuu init\uuuu.py
):
导入错误表明这仍然是一个相当大的漏洞,但除此之外,大多数示例都按照指定的iff工作,包已经加载过一次(即,如果在运行我的问题的语句之前调用了import package
或类似的语句)。如果第一条语句是import package.api
,那么就没有我想要的ImportError
在试图找到这个问题的解决方案时,我无意中发现,这实际上导致了使用更优雅的代码的相同行为:
import sys
from package import api
# clean up this module
self = sys.modules.pop(__name__)
del self
# this module becomes hidden module
sys.modules[__name__] = api
sys.modules[api.__name__] = None
del api
del sys
但是,这仍然存在一个问题,即如果第一次导入类似于
import package.api
,则不会抛出ImportError
我设法写了一些几乎有效的东西(在package/\uuu init\uuuu.py
中):
导入错误表明这仍然是一个相当大的漏洞,但除此之外,大多数示例都按照指定的iff工作,包已经加载过一次(即,如果在运行我的问题的语句之前调用了import package
或类似的语句)。如果第一条语句是import package.api
,那么就没有我想要的ImportError
在试图找到这个问题的解决方案时,我无意中发现,这实际上导致了使用更优雅的代码的相同行为:
import sys
from package import api
# clean up this module
self = sys.modules.pop(__name__)
del self
# this module becomes hidden module
sys.modules[__name__] = api
sys.modules[api.__name__] = None
del api
del sys
但是,这仍然存在一个问题,即如果第一次导入类似于
import package.api
,则不会抛出ImportError
您可以尝试:导入package.code作为code@PeterMajko你这是什么意思?如果导入包,这应该正常工作。code
可以工作…如果使用“从y导入x作为z”,它工作得非常好:@PeterMajko我知道,我注意到tensorflow导入python的确实可以工作(我相应地编辑了我的问题),但它应该工作吗?我假设tensorflow/\uuuu init\uuuuuu.py
中的delpython
的思想是使tensorflow包看起来像是tensorflow/python
。在这种情况下,我不希望看到这种行为,他们有理由这样做。也许会问他们为什么采取这种方法?:)您可以尝试:导入package.code作为code@PeterMajko你这是什么意思?如果导入包,这应该正常工作。code
可以工作…如果使用“从y导入x作为z”,它工作得非常好:@PeterMajko我知道,我注意到tensorflow导入python的确实可以工作(我相应地编辑了我的问题),但它应该工作吗?我假设tensorflow/\uuuu init\uuuuuu.py
中的delpython
的思想是使tensorflow包看起来像是tensorflow/python
。在这种情况下,我不希望看到这种行为,他们有理由这样做。也许会问他们为什么采取这种方法?:)实际上,我希望看到一致的行为: