如何使Python函数中的模块从exec("import xxx")可用?

2024-10-01 00:26:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我为自己编写了一个简单的函数,可以筛选Python文件夹并查找可能的模块所在的位置。我想做的很简单。我传递一个模块导入字符串,函数将在那里找到模块的文件夹cd,并将其导入到我正在工作的任何环境中,例如:

anyimport('from fun_abc import *')

最初我试过:

^{pr2}$

当我在iPython笔记本上写下这一切的时候,它是有效的。所以问题就从我身边溜走了。然后我发现它不能正常工作,因为函数导入的模块停留在函数的局部变量空间中。在

然后我找到了这个堆栈溢出讨论"In Python, why doesn't an import in an exec in a function work?"。因此,我将代码改为:

class anyimport(object):
    def __init__(self, importmodule, pythonpath='/home/user/Python', finddir=finddir):

        ##################################################################    
        ### A BUNCH OF CODES SCANNING THE DIRECTORY AND LOCATE THE ONE ###
        ##################################################################
        ### "pointdir" is where the directory of the file is ###
        ### "evalstr" is a string that looks like this : ---
        ### 'from yourmodule import *'

        sys.path.append(os.path.join(os.path.dirname(__file__), pointdir))
        exec (evalstr, globals())

它仍然不起作用。函数运行时没有错误,但是模块对我不可用,比如说如果我运行script.py,我在其中运行anyimport('from fun_abc import *'),但是{}中没有任何内容。Python会告诉我“NameError:name‘fun_nuyou want’没有定义”。在

有人能给我指出解决这个问题的正确方向吗?在

谢谢你的关注,我真的很感谢你的帮助!在

注意:

除了@Noya当场回答必须通过作用域才能使exec工作之外,为了避免“ImportError”,您还需要在运行exec之前添加以下行:

sys.path.append(os.path.join(os.path.dirname(__file__), pointdir))        
exec (evalstr, scope)

这是因为我们对sys.path的修改假定当前工作目录始终在main/中。我们需要将父目录添加到sys.path。有关解决此问题的详细信息,请参阅此堆栈溢出讨论"ImportError: No module named - Python"。在


Tags: 模块path函数fromimport文件夹isos
2条回答

你可能想试试这样的方法:

_globals = {}
code = """import math;"""
code += """import numpy;"""
code = compile(code, '<string>', 'exec')
exec code in _globals

它比仅仅执行exec更安全,而且应该在函数的局部作用域内正确导入。在

然后,可以使用导入的任何模块(或函数)更新globals()。在

当对函数使用exec时,可以使用g = globals()获得{}的句柄,然后对g进行更新。对于模块,您应该执行另一个步骤。。。您还需要更新sys.modules中的模块。在

更新:明确:

^{pr2}$

exec执行当前作用域中的代码。在函数内部,这意味着(函数)局部作用域。在

通过给exec一个元组(code, scope),可以告诉exec将变量放入另一个范围。例如,可以使用globals()使名称在模块级别可用。在

请注意,globals

is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).

因此,在您的示例中,您必须将所需的范围传递给实用程序函数:

anyimport.py

class anyimport(object):
    def __init__(self, importmodule, scope):
        exec (importmodule, scope)

测试.py

^{pr2}$

主.py

from anyimport import anyimport

if __name__ == '__main__':
    anyimport('from test import *', globals())
    # 42 foo
    print a, b

python main.py测试它。确保所有文件都在当前目录中。在

替代方案

如果不一定要使用exec,一种更优雅的方法是使用Python提供的import实用程序。在

以下内容取自https://stackoverflow.com/a/4526709/453074,相当于from some.package import *

[...] it's more convenient to user importlib:

globals().update(importlib.import_module('some.package').__dict__) 

一。在

相关问题 更多 >