我来到this question并对tensorflow开发人员如何使tensorflow
目录显示为实际包而感到非常失望,而实际的包根实际上是{{1} }}。使用表单
tensorflow/python
文件
__init__.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/__init__.py
是否可以创建import package.api.code
以便以下工作
package/__init__.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
失败的方法。
有人会知道如何做到这一点吗?请随意指出我正在忽视或应考虑实现上述目标的用例。
答案 0 :(得分:0)
首先 - 我必须说我真的很讨厌"阴暗"像这样的技术。它对各种IDE智能感知有不良影响,使得库结构不易理解。但还是......
如果您希望子模块code.py充当实际的子包,则需要创建一个虚拟模块:
package/
__init__.py
api/
__init__.py
code.py
code/
__init__.py
在code / __ init__py中添加:
from package.api.code import *
这在包/ __ init __。py:
中from package.code import *
然后这部分应按预期工作:
import package.code # works as expected
package.code # works as expected
package.code.a # works as expected
from package import a # works as expected
如果你进一步将它添加到包/ __ init __。py:
import package.api
del package.api
您基本上断开了用户与访问package.api的连接,但没有别的,他们仍然可以使用&x 39;来自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'
答案 1 :(得分:0)
我设法写了一些几乎的作品(package/__init__.py
):
import sys
from package.api import *
for key in sys.modules:
parts = key.split('.')
if len(parts) > 1 and parts.pop(0) == __name__:
subkey = parts.pop(0)
if subkey == 'api' and len(parts) == 0:
sys.modules['.'.join([__name__, subkey])] = None
elif subkey == 'api':
m = sys.modules.pop(key)
sys.modules['.'.join([__name__] + parts)] = m
del api
del sys
导入错误表明它仍然非常糟糕,但除此之外,大多数示例都按照指定的工作 iff 包已经加载一次(即import package
在运行我的问题中的语句之前已经调用过类似的东西。如果第一个语句是import package.api
,那么就没有我想要的ImportError
。
为了找到这个问题的解决方案,我偶然发现了this answer,这实际上导致了更优雅代码的相同行为:
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
。