从具有可变文件名

时间:2016-08-18 19:48:18

标签: python python-2.7 import python-import

我有一个具有子功能的函数,我想初始化子函数内部的变量。简单地说,

file = "foo"
def outerFunction():
    def innerFunction():
        var1 = 0
        var2 = 1
        var3 = 2
        print file, var1, var2, var3
    file = "bar"
    innerFunction()
outerFunction()

输出:bar 0 1 2

但是,我在多个不同的文件中有相当多的变量,我想在调用子函数时将它们简单地导入到子函数中。假设我有一个文件bar.py,其中包含以下内容:

var1=0
var2=1
var3=2

然后我将我的代码更改为

file = "foo"
def outerFunction():
    def innerFunction():
        from file import *
        print file, var1, var2, var3
    file = "bar"
    innerFunction()
outerFunction()

这会导致错误,因为当您在子功能中使用import时,Python 2.7不喜欢它。因此,我们可以直接使用__import__函数:

file = "foo"
def outerFunction():
    def innerFunction():
        __import__(file)
        print file, var1, var2, var3
    file = "bar"
    innerFunction()
outerFunction()

这里的导入方法有效,但变量实际上并没有进入子函数的变量列表,导致我打印出来时出错。现在,我知道我可以将代码更改为

file = "foo"
def outerFunction():
    def innerFunction():
        f = __import__(file)
        print file, f.var1, f.var2, f.var3
    file = "bar"
    innerFunction()
outerFunction()

它将起作用桃子。不过,这不是我想要的解决方案。我希望能够导入这些函数,而无需更改我的其余代码以适应。这个问题有更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

从可维护性的角度来看,导入模块然后引用模块的变量是最佳选择。很容易看出变量的来源。

from module import *不受欢迎,因为它很难跟踪变量的来源,特别是如果多个模块包含具有相同名称的变量。 from module import *在函数中是不可能的,因为局部变量在Python中的工作方式。局部变量存储在堆栈中,如果Python不知道将有多少变量,那么它就无法正确地在堆栈上分配空间。

然而,那说,你可以做你所要求的。但你不应该。这背后的想法是将变量引用为全局变量,并在函数启动时相应地更新全局变量。例如

from importlib import import_module

file_ = "foo"
def outer():
    def inner():
        m = import_module(file_) # import module whose name is the contents of file_
        globals().update(m.__dict__) # add module's globals to our own
        print(file_, var0, var1, var2)
    file_ = "bar"
    inner()
outer()

这是一个可怕的想法,因为每个内部函数将共享同一组全局变量,并且可能覆盖具有相同名称的变量。如果同时运行inner函数,或者它们覆盖定义outer的模块所需的变量,则会导致问题。可以通过修改每个inner函数来使用它自己独特的全局变量来克服这一点,但这是一个可怕的黑客攻击,主要包括显示这是如何可能的。

from importlib import import_module
from types import FunctionType

file_ = "foo"
def outer():
    def inner():
        m = import_module(file_)
        globals().update(m.__dict__)
        print(file_, var0, var1, var2)
    # redefine inner with new globals
    inner = FunctionType(inner.__code__, 
        dict(import_module=import_module, __builtins__=__builtins__), # new globals
        inner.__name__, inner.__defaults__, inner.__closure__
    )
    file_ = "bar"
    inner()
outer()