2

我以两种不同的方式导入了一个numpy库。第一次from numpy.random import mtrand和第二次弄乱了sys.path.

但是,这两个模块导入的输出完全不同:

>>> from numpy.random import mtrand
>>> dir(mtrand)
['RandomState', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__test__', '_rand', 'beta', 'binomial', 'bytes', 'chisquare', 'dirichlet', 'exponential', 'f', 'gamma', 'geometric', 'get_state', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'np', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random_integers', 'random_sample', 'rayleigh', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf']

第二个:

>>> sys.path.insert(0, '/usr/lib/pymodules/python2.7/numpy/random')
>>> import mtrand
>>> dir(mtrand)
['__builtins__', '__doc__', '__file__', '__name__', '__package__']

这种行为怎么可能?

编辑:

  • 这两个测试是在不同的 python 进程中执行的。
  • 弄乱 sys 路径是愚蠢的,我知道。但这不适用于普通程序,而是用于自动完成。我当然不想导入整个 numpy 包。我只想做一个dir(mtrand)
4

3 回答 3

2

尝试导入扩展模块(即从共享库加载的模块)两次会导致未定义的行为。从以下文档中引用reload()

然而,在许多情况下,扩展模块不会被设计为多次初始化,并且在重新加载时可能会以任意方式失败。

顺便说一句,这恰好适用于我的安装numpy

>>> from numpy.random import mtrand
>>> dir(mtrand)
['RandomState', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__test__', '_rand', 'beta', 'binomial', 'bytes', 'chisquare', 'dirichlet', 'exponential', 'f', 'gamma', 'geometric', 'get_state', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'np', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random_integers', 'random_sample', 'rayleigh', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf']
>>> sys.path.append("/usr/lib/pyshared/python2.7/numpy/random")
>>> import mtrand
>>> dir(mtrand)
['RandomState', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__test__', '_rand', 'beta', 'binomial', 'bytes', 'chisquare', 'dirichlet', 'exponential', 'f', 'gamma', 'geometric', 'get_state', 'gumbel', 'hypergeometric', 'laplace', 'logistic', 'lognormal', 'logseries', 'multinomial', 'multivariate_normal', 'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'np', 'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random_integers', 'random_sample', 'rayleigh', 'seed', 'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'triangular', 'uniform', 'vonmises', 'wald', 'weibull', 'zipf']

这是未定义的行为,所以任何事情都可能发生。

于 2012-04-16T22:50:51.133 回答
0

不知道为什么有人为此给你一个-1。在遇到我自己的 Python 导入问题后,我认为当你弄乱了之后,sys.path你已经绕过了通常会执行 的init .py 文件。/usr/lib/pymodules/python2.7/numpy并且/usr/lib/pymodules/python2.7/numpy/random(可能)是 python 包并包含init .py 文件。每当导入该包或子包中的任何内容时,默认情况下都会包含初始化文件。通过将路径指向文件树的更深层次,您绕过了这些初始化文件,从而改变了包的预期行为。

斯文也提供了很好的信息。我假设您的 2 个导入不在 Python 的同一个运行实例中。如果是,那么 Sven 的回答是相关的。

于 2012-04-16T22:50:18.253 回答
0

正如 Endophage 指出的那样,玩sys.path. 但我想我开始了它,因为我不想执行任何 Python 代码,这对于自动完成来说非常酷。我不认为这对于 c_builtin 模块来说是个大问题。但是,有些模块确实需要正确的包路径(请参阅下面关于 segfaults 的评论)。

我什至做了一个解决方法PyQt4,但注意到这不是唯一的解决方法:

sys.path.append('/usr/lib/python2.7/dist-packages/PyQt4')
try:
    import QtCore
except SystemError:
    QtCore = sys.modules['PyQt4.QtCore']
    debug.warning('Loaded a module with SystemError.') 

这包括捕获 aSystemError然后从 sys.modules 中使用它。确实这是非常愚蠢的,因为我不知道此类操作的任何副作用。正如我测试PySide的(这是另一个 Qt 包装器),在某些情况下会发生段错误。

所以我想出了更pythonic的解决方案来再次加载这样的模块:from PyQt4 import QtCorefrom numpy.random import random.

有趣的是,使用完整路径加载这些模块的内存占用量与sys.path.

于 2012-08-01T13:04:08.223 回答