(重要提示:请参阅下面的更新。)
我正在尝试编写一个对某些模块很重要的函数import_something
。 (对于这个问题,这并不重要。)问题是,我希望在调用函数的级别导入这些模块。例如:
import_something() # Let's say this imports my_module
my_module.do_stuff() #
这可能吗?
更新
对不起,我原来的措辞和例子都是误导。我会尝试解释我的整个问题。我所拥有的是一个包,其中包含一些模块和包。在__init__.py
我要导入所有模块和包。所以在程序的其他地方,我导入整个包,并迭代它导入的模块/包。
(为什么?这个包名为crunchers
,在其中定义了所有类型的crunchers,如CruncherThread
,CruncherProcess
,以及将来MicroThreadCruncher
我希望crunchers包自动包含放在其中的所有crunchers,所以稍后在程序中我使用crunchers
我知道它可以准确地告诉我已经定义了哪些crunchers。)
我知道如果我完全避免使用函数,我可以解决这个问题,并使用for
循环等在主级别上执行所有导入。但它很难看,我想知道我是否可以避免它。
如果还有其他问题,请在评论中提问。
答案 0 :(得分:4)
函数可以将某些内容返回到调用它们的位置。它称为返回值:p
def import_something():
# decide what to import
# ...
mod = __import__( something )
return mod
my_module = import_something()
my_module.do_stuff()
好风格,没有麻烦。
关于您的更新,我认为向您__init__.py
添加这样的内容可以满足您的需求:
import os
# make a list of all .py files in the same dir that dont start with _
__all__ = installed = [ name for (name,ext) in ( os.path.splitext(fn) for fn in os.listdir(os.path.dirname(__file__))) if ext=='.py' and not name.startswith('_') ]
for name in installed:
# import them all
__import__( name, globals(), locals())
其他地方:
import crunchers
crunchers.installed # all names
crunchers.cruncherA # actual module object, but you can't use it since you don't know the name when you write the code
# turns out the be pretty much the same as the first solution :p
mycruncher = getattr(crunchers, crunchers.installed[0])
答案 1 :(得分:1)
您可以使用CPython中的父框架将模块安装到该框架的本地(并且只有该框架)。缺点是:a)这真的非常hackish b)sys._getframe()不保证在其他python实现中存在。
def importer():
f = sys._getframe(1) # Get the parent frame
f.f_locals["some_name"] = __import__(module_name, f.f_globals, f.f_locals)
您仍然需要将模块安装到f_locals中,因为import实际上不会为您执行此操作 - 您只需为正确的上下文提供父帧本地和全局变量。
然后在您的通话功能中,您可以:
def foo():
importer() # Magically makes 'some_name' available to the calling function
some_name.some_func()
答案 2 :(得分:1)
你在找这样的东西吗?
def my_import(*names):
for name in names:
sys._getframe(1).f_locals[name] = __import__(name)
然后你可以这样称呼它:
my_import("os", "re")
或
namelist = ["os", "re"]
my_import(*namelist)
答案 3 :(得分:0)
根据__import__
的帮助:
__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module
Import a module. The globals are only used to determine the context;
they are not modified. ...
因此,您只需获取父框架的全局变量并将其用于__import__
调用。
def import_something(s):
return __import__(s, sys._getframe(1).f_globals)
注意:2.6之前,__import__
的签名不同之处在于它只有可选参数而不是使用kwargs。由于globals
是两种情况下的第二个参数,因此上面调用的方式运行正常。如果您决定使用任何其他参数,请注意一些事项。