如何强制Python的“导入”将名称视为模块,而不是函数?

时间:2016-12-19 00:22:54

标签: python python-2.7 import

我正在使用SymPy,遇到以下问题:

>>> import sympy.utilities.lambdify
>>> sympy.utilities.lambdify
<function lambdify at 0x0000000003802B38>

等等,sympy.utilities.lambdify不应该是一个模块吗?

>>> from sympy.utilities.lambdify import implemented_function
>>> implemented_function
<function implemented_function at 0x0000000003802CF8>
>>> implemented_function.__module__
'sympy.utilities.lambdify'

哦,所以存在命名冲突。

现在显然我可以使用implemented_function,但这不是我的问题。

我的问题是:如何导入sympy.utilities.lambdify 模块而不是功能

(我在这里只是使用SymPy进行说明。这是否是正确的库使用是不重要的。来源是here。)

3 个答案:

答案 0 :(得分:4)

实际上,看起来这可以用importlib完全干净地完成:

import {Component} from '@angular/core';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'my-app',
    template: `    
               <input id="search" type="text" class="form-control" placeholder="Search"/>
    `
})
export class AppComponent{
    constructor() {

        var input = $('#search');

        var keyups = Observable.fromEvent(input, 'keyup');

        keyups.subscribe(data => console.log(data));
    }
}

评论编辑(感谢@Mehrdad):

或者,如果您想避免将模块名称放在字符串中,您可以这样做:

import importlib
lamdify = importlib.import_module('sympy.utilities.lambdify')
print lambdify
  <module 'sympy.utilities.lambdify' from 'c:\python-2.7.8-amd64\lib\site-packages\sympy\utilities\lambdify.pyc'>

用法:def import_module(lambda_): import importlib; return importlib.import_module('.'.join(lambda_.__code__.co_names))

虽然这看起来有点长,对我来说不太清楚。

答案 1 :(得分:2)

明显的不一致是由于lambdify不是模块,它是包含多个函数定义的python文件。请在名为bar.py的文件中考虑以下示例:

def foo(): pass

def bar(): pass

然后from bar import bar; print(bar.__module__)会给你'bar'

lambdify可以导入__init__的原因是sympy.utilities from .lambdify import lambdify 中的一行:

lambdify.py

也就是说,在sympy.utilities模块的lambdify()文件中,有sympy.utilities的定义,并将其导入sympy.utilities命名空间。因此,当您导入import时,您可以访问lambdify。但您仍可lambdify.py from sympy.utilities.lambdify import ... bar.py中定义__init__py其他函数。{/ 1>

您的实际问题是您是否可以导入这样的模块。好吧,你可以,但你可能不应该。让我们使用上面的from .bar import bar 对情况进行建模,并通过创建tmp使其成为一个包:

tmp

将这两个文件放在名为bar的目录中,我们得到一个模型,其中包含一个名为__init__.py的模块和一个&#34;子模块&#34; tmp.bar(但我不认为它是一个合适的子模块,缺少sympy)。如果我们导入>>> import tmp >>> tmp <module 'tmp' from '/home/user/python/tmp/__init__.py'> >>> import tmp.bar >>> tmp.bar <function bar at 0x7f24426461e0> >>> tmp.bar.foo Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'function' object has no attribute 'foo' >>> from tmp.bar import foo >>> foo <function foo at 0x7f2442646158> ,就会发生同样的事情,就像tmp.bar一样:

sys.modules

所以>>> import sys >>> 'tmp' in sys.modules False >>> import tmp.bar >>> tmp.bar <function bar at 0x7fc833025158> >>> 'tmp.bar' in sys.modules True >>> tmp.bar.foo Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'function' object has no attribute 'foo' >>> sys.modules['tmp.bar'].foo <function foo at 0x7fc833020f28> 指的是函数而不是模块。显然。但实际上它也允许访问模块,尽管它被同名函数遮蔽了!

让我们重复以上内容,但继续监控tmp.bar

sys.modules['tmp.bar']

因此,虽然>>> import sys >>> import sympy.utilities.lambdify >>> lambdify_module = sys.modules['sympy.utilities.lambdify'] >>> lambdify_module.implemented_function <function implemented_function at 0x7fc83183ca60> 引用了本地命名空间中的函数,但我们可以通过来自同一导入的{{1}}访问模块本身。

只是要明确:

{{1}}

答案 2 :(得分:0)

这特定于sympy的结构。请参阅实用程序__init__.py的源代码line

from .lambdify import lambdify

从本地模块lambdify导入功能 lambdify;因此utilities.lambdify功能

假设您希望真正导入模块,而不是函数lambdify。也许是这样的,

import os
import imp

import sympy.utilities as mod
sub_mod_name = 'lambdify'
sub_mod_file = '{}.py'.format(sub_mod_name)

mod_loc = os.path.dirname(mod.__file__)
file_ = os.path.join(mod_loc, sub_mod_file)  # Full path for source file
sub_mod = imp.load_source(sub_mod_name, file_)  # Import module from source file

print sub_mod
# <module 'lambdify' from '/usr/local/lib/python2.7/dist-packages/sympy/utilities/lambdify.pyc'>