Python相对于科学堆栈中的绝对导入

时间:2018-04-08 18:11:33

标签: python numpy import scipy

我正在查看以下软件包(numpy,scipy,scikit-learn,scikit-image),以获取有关如何构建自己的软件的灵感。在我列出的软件包中似乎是标准的东西是以下约定:

  1. 在所有情况下,导入都会显示在每个文件的顶部
  2. 在“模块代码”中,所有“内部包”导入都是使用相对导入
  3. 完成的
  4. 在“模块代码”中,所有“外部包”导入都是使用绝对导入
  5. 完成的
  6. 在“测试代码”中,仅使用绝对导入
  7. 有人可以解释为什么要使用这些规则,或者指点一些参考?在他们所有的编码惯例指南中,他们声明遵循这个标准,但我没有看到为什么做出解释。我很想知道,所以任何帮助都非常感谢!

    以下是一些有助于说明的代码示例......

    “模块代码示例”(sklearn / decomposition / pca.py)

    from math import log, sqrt
    import numbers
    
    import numpy as np
    from scipy import linalg
    from scipy.special import gammaln
    from scipy.sparse import issparse
    from scipy.sparse.linalg import svds
    
    from ..externals import six
    
    from .base import _BasePCA
    from ..base import BaseEstimator, TransformerMixin
    from ..utils import deprecated
    from ..utils import check_random_state, as_float_array
    from ..utils import check_array
    from ..utils.extmath import fast_logdet, randomized_svd, svd_flip
    from ..utils.extmath import stable_cumsum
    from ..utils.validation import check_is_fitted
    
    
    def _assess_dimension_(spectrum, rank, n_samples, n_features):
        """Compute the likelihood of a rank ``rank`` dataset
    
        The dataset is assumed to be embedded in gaussian noise of shape(n,
        dimf) having spectrum ``spectrum``.
    
        Parameters
        ----------
        spectrum : array of shape (n)
            Data spectrum.
    

    测试代码示例(sklearn / decomposition / tests / test_pca.py)

    import numpy as np
    import scipy as sp
    from itertools import product
    
    from sklearn.utils.testing import assert_almost_equal
    from sklearn.utils.testing import assert_array_almost_equal
    from sklearn.utils.testing import assert_true
    from sklearn.utils.testing import assert_equal
    from sklearn.utils.testing import assert_greater
    from sklearn.utils.testing import assert_raise_message
    from sklearn.utils.testing import assert_raises
    from sklearn.utils.testing import assert_raises_regex
    from sklearn.utils.testing import assert_no_warnings
    from sklearn.utils.testing import assert_warns_message
    from sklearn.utils.testing import ignore_warnings
    from sklearn.utils.testing import assert_less
    
    from sklearn import datasets
    from sklearn.decomposition import PCA
    from sklearn.decomposition import RandomizedPCA
    from sklearn.decomposition.pca import _assess_dimension_
    from sklearn.decomposition.pca import _infer_dimension_
    
    iris = datasets.load_iris()
    solver_list = ['full', 'arpack', 'randomized', 'auto']
    
    
    def test_pca():
        # PCA on dense arrays
        X = iris.data
    
        for n_comp in np.arange(X.shape[1]):
            pca = PCA(n_components=n_comp, svd_solver='full')
    
            X_r = pca.fit(X).transform(X)
            np.testing.assert_equal(X_r.shape[1], n_comp)
    

1 个答案:

答案 0 :(得分:3)

我认为您可以通过查看所引用代码中的某个导入来了解您描述的样式为何受欢迎的原因:

from ..externals import six

此导入从six包中获取sklearn.internals模块。但是six是一个可以单独分发的模块。它已由sklearn项目“推销”。提供模块意味着他们将自己的副本包含在自己的项目中,而不是将其作为外部依赖项。

让您的包裹可以出售是您可能喜欢相对进口的一个原因。如果您的软件包通常名为my_package,但其他项目已将其作为some_other_package.externals.my_package出售,则如果使用相对导入语法,则内部导入仍然有效。如果你使用绝对导入,他们都会破坏(并且销售项目需要重写每个)。

虽然不完美。另一个包需要编辑你的导入,如果他们还出售你的一些外部依赖项(你使用绝对导入访问)。在修复错误时,供应也有一些严重的缺点。如果软件包的销售版本存在安全漏洞,那么包含它的项目也是如此。如果外部包只访问其依赖项的外部版本,则可以从外部程序包的修复中受益,而无需自行更改。

值得注意的是,一些Python开发人员对当前系统的工作方式并不完全满意,因为解决一些常见问题可能很难。 A recent thread on the Python-dev mailing list讨论了目前的支持是如何不完善的。

供应可能很尴尬,而且经常会被像Linux发行版这样需要能够可靠地修复安全漏洞的下游打包者所取消。但是没有它,包很难依赖于依赖项中特定于版本的行为。没有版本的导入,所以如果你的代码在some_package从版本1.9升级到2.0时中断,那么你就无法做到这一点(除了也许跳过一大堆箍尝试一次支持你的两个版本的依赖项。)