我正在尝试使用from foo.bar import object
函数复制__import__
,而我似乎遇到了问题。
from glob import glob
很简单:
glob = __import__("glob",glob)
或glob = __import__("glob").glob
我遇到的问题是我从包中导入(即bar),我希望包中的脚本成为导入源。
所以我想要的是
string_to_import = "bar"
object = __import__("foo",string_to_import).object
但这只是导入foo包中的__init__
。
如何做到这一点?
编辑:
当我使用显而易见的时候,只有__init__
被称为
__import__("foo.bar")
<module 'foo' from 'foo/__init__.pyc'>
答案 0 :(得分:36)
__import__
函数将返回包的顶级模块,除非您传递非空fromlist
参数:
_temp = __import__('foo.bar', fromlist=['object'])
object = _temp.object
请参阅__import__
function上的Python文档。
答案 1 :(得分:26)
如何正确使用python&#39;
__import__()
功能?
有两种用途:
在大多数情况下,你真的不需要这样做。
最佳做法是使用importlib
代替。但如果你坚持:
琐碎的用法:
>>> sys = __import__('sys')
>>> sys
<module 'sys' (built-in)>
复杂:
>>> os = __import__('os.path')
>>> os
<module 'os' from '/home/myuser/anaconda3/lib/python3.6/os.py'>
>>> os.path
<module 'posixpath' from '/home/myuser/anaconda3/lib/python3.6/posixpath.py'>
如果您想在名称中使用最右边的子模块,请传递非空列表,例如[None]
,fromlist
:
>>> path = __import__('os.path', fromlist=[None])
>>> path
<module 'posixpath' from '/home/myuser/anaconda3/lib/python3.6/posixpath.py'>
或者,正如文档所声明的那样,使用importlib.import_module
:
>>> importlib = __import__('importlib')
>>> futures = importlib.import_module('concurrent.futures')
>>> futures
<module 'concurrent.futures' from '/home/myuser/anaconda3/lib/python3.6/concurrent/futures/__init__.py'>
__import__
的文档是内置函数中最令人困惑的。
__import__(...)
__import__(name, globals=None, locals=None, fromlist=(), level=0) -> module
Import a module. Because this function is meant for use by the Python
interpreter and not for general use it is better to use
importlib.import_module() to programmatically import a module.
The globals argument is only used to determine the context;
they are not modified. The locals argument is unused. The fromlist
should be a list of names to emulate ``from name import ...'', or an
empty list to emulate ``import name''.
When importing a module from a package, note that __import__('A.B', ...)
returns package A when fromlist is empty, but its submodule B when
fromlist is not empty. Level is used to determine whether to perform
absolute or relative imports. 0 is absolute while a positive number
is the number of parent directories to search relative to the current module.
如果您仔细阅读,您会发现API最初旨在允许从模块中延迟加载函数。但是,这不是CPython的工作方式,而且我不知道Python的任何其他实现是否已成功实现。
相反,CPython在第一次导入时执行模块命名空间中的所有代码,之后模块被缓存在sys.modules
中。
__import__
仍然有用。但是根据文档理解它的作用是相当困难的。
__import__
要调整完整功能以演示当前的__import__
API,这里有一个包装函数,它带有更清晰,更好的文档API。
def importer(name, root_package=False, relative_globals=None, level=0):
""" We only import modules, functions can be looked up on the module.
Usage:
from foo.bar import baz
>>> baz = importer('foo.bar.baz')
import foo.bar.baz
>>> foo = importer('foo.bar.baz', root_package=True)
>>> foo.bar.baz
from .. import baz (level = number of dots)
>>> baz = importer('baz', relative_globals=globals(), level=2)
"""
return __import__(name, locals=None, # locals has no use
globals=relative_globals,
fromlist=[] if root_package else [None],
level=level)
要证明,例如从姊妹套餐到巴兹:
baz = importer('foo.bar.baz')
foo = importer('foo.bar.baz', root_package=True)
baz2 = importer('bar.baz', relative_globals=globals(), level=2)
assert foo.bar.baz is baz is baz2
要从baz模块按名称动态访问全局变量,请使用getattr
。例如:
for name in dir(baz):
print(getattr(baz, name))
您可以使用__import__
来更改或拦截导入行为。在这种情况下,让我们只打印它所获得的论据,以证明我们正在拦截它:
old_import = __import__
def noisy_importer(name, locals, globals, fromlist, level):
print(f'name: {name!r}')
print(f'fromlist: {fromlist}')
print(f'level: {level}')
return old_import(name, locals, globals, fromlist, level)
import builtins
builtins.__import__ = noisy_importer
现在当你导入时,你可以看到这些重要的论点。
>>> from os.path import join as opj
name: 'os.path'
fromlist: ('join',)
level: 0
>>> opj
<function join at 0x7fd08d882618>
也许在这种情况下,获取全局变量或局部变量可能很有用,但不会立即想到这一点。
答案 2 :(得分:20)
您应该使用importlib.import_module
,在解释器之外不建议使用__import__
。
在__import__
的文档字符串中:
导入模块。因为这个函数适合Python使用 口译员而不是一般用途,最好使用 importlib.import_module()以编程方式导入模块。
它还支持relative imports。
答案 3 :(得分:3)
我不使用__import__
函数,而是使用getattr函数:
model = getattr(module, model_s)
其中module是要查看的模块,而model_s是您的模型字符串。 __import__
函数并不是松散使用的,因为这个函数可以为你提供你想要的东西。