简体   繁体   English

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

[英]Python relative vs absolute imports in scientific stack repos

I'm looking at the following packages (numpy, scipy, scikit-learn, scikit-image) for inspiration on how to structure my own software. 我正在查看以下软件包(numpy,scipy,scikit-learn,scikit-image),以获取有关如何构建自己的软件的灵感。 Something that seems to be standard across the packages I listed are the following conventions: 在我列出的软件包中似乎是标准的东西是以下约定:

  1. In all cases, imports appear at the top of each file 在所有情况下,导入都显示在每个文件的顶部
  2. In "module code", all "internal package" imports are done using relative imports 在“模块代码”中,所有“内部包”导入都是使用相对导入完成的
  3. In "module code", all "external package" imports are done using absolute imports 在“模块代码”中,所有“外部包”导入都是使用绝对导入完成的
  4. In "test code", only absolute imports are used 在“测试代码”中,仅使用绝对导入

Could someone explain why these rules are being used, or point me to some references? 有人可以解释为什么要使用这些规则,或者指点一些参考? In all of their coding convention guides they state to follow this standard, but I don't see an explanation on why. 在他们所有的编码惯例指南中,他们声明遵循这个标准,但我没有看到为什么做出解释。 I'd love to know, so any help is much appreciated! 我很想知道,所以任何帮助都非常感谢!

Here are a few code examples to help illustrate... 以下是一些有助于说明的代码示例...

"Module code example" (sklearn/decomposition/pca.py) “模块代码示例” (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.

Test code example (sklearn/decomposition/tests/test_pca.py) 测试代码示例 (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)

I think you can get a hint at why the style you describe is popular by looking at one of the imports in the code you quoted: 我想你可以通过查看你引用的代码中的一个导入来了解为什么你描述的样式很受欢迎:

from ..externals import six

This import gets the six module from inside the sklearn.internals package. 此导入从sklearn.internals包中获取six模块。 But six is a module that can be distributed separately. six是一个可以单独分发的模块。 It's been "vendored" by the sklearn project. 它已经被sklearn项目“推销”了。 Vendoring a module means they're including their own copy of it inside their own project, rather than having it as an external dependency. 提供模块意味着他们将自己的副本包含在自己的项目中,而不是将其作为外部依赖项。

Making it possible for your package to be vendored is one reason you might favor relative imports. 使您的包裹可以出售是您可能喜欢相对进口的一个原因。 If your package is normally named my_package , but some other project has vendored it as some_other_package.externals.my_package , your internal imports will still work if you used relative import syntax. 如果您的软件包通常名为my_package ,但其他一些项目已将其作为some_other_package.externals.my_package ,那么如果使用相对导入语法,则内部导入仍然有效。 If you used absolute imports, they'd all break (and the vendoring project would need to rewrite each of them). 如果您使用绝对导入,它们都会中断(并且出售项目需要重写每个进程)。

It isn't perfect though. 虽然它并不完美。 The other package will need to edit your imports if they're also vendoring some of your external dependencies (that you're accessing with absolute imports). 另一个包需要编辑你的导入,如果他们还出售你的一些外部依赖项(你使用绝对导入访问)。 Vendoring also has some severe downsides when it comes to fixing bugs. 在修复错误时,供应也有一些严重的缺点。 If the vendored version of a package has a security flaw, then so does the project including it. 如果软件包的销售版本存在安全漏洞,那么包含它的项目也是如此。 If the outer package only accessed an external version of its dependency, it could benefit from a fix to the external package without needing to be changed itself. 如果外部包只访问其依赖项的外部版本,则可以从外部程序包的修复中受益,而无需自行更改。

It's worth noting that some Python developers are not entirely happy with how the current system works, as it can be hard to resolve some common issues. 值得注意的是,一些Python开发人员对当前系统的工作原理并不完全满意,因为解决一些常见问题可能很难。 A recent thread on the Python-dev mailing list discussed how the current support is imperfect. Python-dev邮件列表中最近的一个帖子讨论了当前支持是如何不完美的。

Vendoring can be awkward, and it is often undone by downstream packagers, like Linux distros, who need to be able to reliably fix security vulnerabilities. 供应可能很尴尬,而且通常会被Linux发行版等需要能够可靠地修复安全漏洞的下游打包程序所取消。 But without it, it's hard to for a package to rely upon version-specific behavior from its dependencies. 但是没有它,包很难依赖于依赖项中特定于版本的行为。 There's no versioning of imports, so if your code breaks when some_package gets upgraded from version 1.9 to 2.0, there's not much you can do about it (except maybe jump through a whole bunch of hoops to try to support both versions of your dependency at once). 没有版本的导入,所以如果你的代码在some_package从1.9版本升级到2.0时some_package了,你就无法做到这一点(除了可能会跳过一大堆箍以尝试同时支持两个版本的依赖项) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM