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

anyimport('from fun_abc import *')

最初我试过:
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 *'

        os.chdir(pointdir)
        exec evalstr

当我在 iPython Notebook 中对整个内容进行编码时,它可以工作。所以这个问题被我忽略了。然后我发现它不能正常工作,因为函数导入的模块保留在函数的局部变量空间中。

然后我发现了这个 Stack Overflow 讨论 "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 *') 但没有 fun_abc 中的任何内容。 Python 会告诉我“NameError: name 'fun_you_want' is not defined”。

有没有人愿意为我指出如何解决这个问题的正确方向?

感谢您的关注,非常感谢您的帮助!

注意力:

除了@Noya 的现场回答,必须通过范围才能使 exec 工作,以避免“ImportError”,您需要在运行 exec 之前添加这一行:
sys.path.append(os.path.join(os.path.dirname(__file__), pointdir))
exec (evalstr, scope)

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

最佳答案

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

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

请注意,globals



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

anyimport.py:

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

测试.py:
a = 42
b = 'foo'

主要.py:
from anyimport import anyimport

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

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

替代方案

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

以下取自 https://stackoverflow.com/a/4526709/453074 ,等效于 from some.package import * :


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

.

关于python - 如何使来自 exec ("import xxx") 的模块在 Python 函数中可用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28481170/

10-14 17:38
查看更多