gpt4 book ai didi

python - 什么是沙漏导入,为什么要在代码库中避免它们?

转载 作者:行者123 更新时间:2023-12-03 14:34:16 25 4
gpt4 key购买 nike

我看到了some commits在 Python 代码库中删除“沙漏导入”。我以前从未见过这个术语,也无法通过 Python 文档或网络搜索找到任何关于它的信息。

什么是沙漏进口,什么时候使用或不使用它们? 我最好的猜测是删除它们会生成子模块 easier to find ,但还有其他原因吗?

从其中一个链接提交中删除沙漏导入的示例更改:

diff --git a/tensorflow/contrib/slim/python/slim/nets/vgg.py b/tensorflow/contrib/slim/python/slim/nets/vgg.py
index 3c29767f2..d4eb43cbb 100644
--- a/tensorflow/contrib/slim/python/slim/nets/vgg.py
+++ b/tensorflow/contrib/slim/python/slim/nets/vgg.py
@@ -37,13 +37,20 @@ Usage:
@@vgg_16
@@vgg_19
"""
+
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

-import tensorflow as tf
-
-slim = tf.contrib.slim
+from tensorflow.contrib import layers
+from tensorflow.contrib.framework.python.ops import arg_scope
+from tensorflow.contrib.layers.python.layers import layers as layers_lib
+from tensorflow.contrib.layers.python.layers import regularizers
+from tensorflow.contrib.layers.python.layers import utils
+from tensorflow.python.ops import array_ops
+from tensorflow.python.ops import init_ops
+from tensorflow.python.ops import nn_ops
+from tensorflow.python.ops import variable_scope


def vgg_arg_scope(weight_decay=0.0005):

顶级 tensorflow __init__.py从子模块中导出符号。

# tensorflow/python/__init__.py
...
from tensorflow.python.ops.standard_ops import *
...

# tensorflow/python/ops/standard_ops.py
...
from tensorflow.python.ops.array_ops import *
from tensorflow.python.ops.check_ops import *
from tensorflow.python.ops.clip_ops import *
...

最佳答案

TensorFlow 贡献者在这里 :wave:.我们使用沙漏这个词
import 引用从其他模块导入一堆东西的模块
模块并重新导出它们。你在你的文章中提供了一个很好的例子
问题。
我们关心这个的原因以及我们称之为
沙漏都与构建图的形状有关。整体
沙漏模块的要点是很多用户将依赖它作为
一个方便的入口点。它本身取决于很多内部
符号。所以你的依赖图有很多边通过这个
一个节点,通过 hourglass 的中心汇集:
Diagram of a simple build graph with three end-user binariesdepending on :standard_ops, and :standard_ops depending on threeinternal targets.
在现实世界中,沙漏会更宽更深
比这,在双方。最终用户可以定义依赖于:standard_ops和依赖于这些库的二进制文件,以及
内部操作本身可能具有依赖层。
这样做的问题在于,它很难以低廉的价格和正确的
重新构建以应对变化。如果我们更改 :check_ops 的一部分, 然后
看起来像 :standard_ops需要重建,因为其中之一
依赖关系发生了变化。因为:standard_ops已经重建,
它的依赖关系也必须如此。但现在我们重新构建了所有最终用户
程序,即使他们甚至没有实际使用该功能
:check_ops 提供一点也不。我们说构建图
过度逼近实际的依赖图。过度近似是
声音——构建仍然是正确的——但它可能是浪费的。
这是像 TensorFlow 这样的大型代码库的问题,我们有很多
数千个测试,当您更改任何代码时,我们会运行所有受影响的测试,
并且测试可能很昂贵。如果你估计“哪些测试是
受到这种变化的影响?”是一个巨大的过度近似,由于
沙漏依赖,你在测试上浪费了大量的计算能力,
并且您的开发人员还必须等待更长的时间才能合并他们的更改。
您原始问题中的补丁显示了我们如何删除
沙漏依赖并重写客户端以直接指向那些
他们实际使用的构建图的部分:
Diagram of a more precise build graph, with edges from end-userprograms to just those targets that they actually need
这样,如果 :check_ops改变了,我们可以看到我们只需要
重新构建并重新测试一个客户端。
这有好处也有坏处。对于真正的最终用户,必须
直接导入大量内部组件很烦人。这不是一个很好的 API,
不如import numpy as np好或 import tensorflow as tf .
此外,它暴露了实现细节,使我们更难
在这些模块中移动。因此,出于这些原因,我们仍然
向用户提供沙漏导入,无论是在公开场合还是在 Google 内部。
但是,我们尽量不在我们自己的内部使用沙漏导入
代码库。在我们自己的存储库中,重大更改不是问题,
因为如果我们想重命名某些东西,我们可以重命名它的所有客户
同时。我们有 tools for working with our buildgraphs并且很乐意这样做,这是
大多数 Python 程序员不想担心。工具是
不过非常好——除了生成漂亮的可视化图形(如
以上)对于您的真实代码库,它们是强大的查询引擎的基础,
您可以在其中询问系统问题,例如“哪些目标是
传递地依赖于 :foo仍在 Python 2 上运行并且属于
给我的团队?”。当您的构建图更多时,这会更强大
精确的。
TL;DR: 沙漏模块是一个捆绑了许多进口的模块
子模块并将它们公开给许多客户端模块。我们避免他们
因为它过度近似了构建图,这使得它更
运行测试成本高,分析代码更难。

关于python - 什么是沙漏导入,为什么要在代码库中避免它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43221870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com