Python:通过函数导入到主命名空间

时间:2009-11-03 17:25:50

标签: python import

(重要提示:请参阅下面的更新。)

我正在尝试编写一个对某些模块很重要的函数import_something。 (对于这个问题,这并不重要。)问题是,我希望在调用函数的级别导入这些模块。例如:

import_something() # Let's say this imports my_module
my_module.do_stuff() #

这可能吗?

更新

对不起,我原来的措辞和例子都是误导。我会尝试解释我的整个问题。我所拥有的是一个包,其中包含一些模块和包。在__init__.py我要导入所有模块和包。所以在程序的其他地方,我导入整个包,并迭代它导入的模块/包。

(为什么?这个包名为crunchers,在其中定义了所有类型的crunchers,如CruncherThreadCruncherProcess,以及将来MicroThreadCruncher我希望crunchers包自动包含放在其中的所有crunchers,所以稍后在程序中我使用crunchers我知道它可以准确地告诉我已经定义了哪些crunchers。)

我知道如果我完全避免使用函数,我可以解决这个问题,并使用for循环等在主级别上执行所有导入。但它很难看,我想知道我是否可以避免它。

如果还有其他问题,请在评论中提问。

4 个答案:

答案 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是两种情况下的第二个参数,因此上面调用的方式运行正常。如果您决定使用任何其他参数,请注意一些事项。