【问题标题】:Dynamically import via variable a relative script in Python通过变量动态导入Python中的相关脚本
【发布时间】:2014-04-30 21:03:21
【问题描述】:

在我的主要 Python 脚本中,调用了一个 Web API。该调用的结果决定了需要运行什么“协议”。这些协议是一个名为 protocols/ 的子文件夹中的单独 python 脚本。

那么,如何从我的主脚本中动态调用这些脚本之一?脚本名称是来自 API 的变量,它位于主脚本的子文件夹中 - 而不是标准库位置。

我可以使用subprocess.popenos.system,但我希望一切都尽可能在内部进行。

必须有一种方法可以在一个 Python 实例中完成此任务,对吧?

【问题讨论】:

    标签: python python-import


    【解决方案1】:

    有一个 Python 内置函数可以处理调用脚本。

    它被称为execfile,您可以在以下位置了解更多信息:

    https://docs.python.org/2/library/functions.html#execfile

    如果我有一个名为 testmeagain.py 的文件,内容如下:

    print "test print"
    

    您可以在不导入其他库的情况下执行此操作:

    In [1]: execfile("testmeagain.py")
    test print
    

    【讨论】:

      【解决方案2】:

      假设您从该目录运行您的主要 Python 程序,该目录将 protocols 视为子文件夹,您应将空的 __init__.py 添加到 protocols 目录以使其成为一个包。

      然后您就可以从那里导入您的协议特定模块,例如

      from protocols.http import process_it
      

      在这里我假设,你会有一些名为process_it的函数

      还有其他方法,如何导入名称在变量中定义的包,如描述的,例如在这个 SO 答案中enter link description here

      在你的情况下,它看起来像:

      def process_it(protocol="http"):
          mod = __import__("protocols." + protocol)
          mod.process_it()
      

      【讨论】:

        【解决方案3】:

        是的,有可能在一个 Python 实例中完成此操作。可以动态加载单个 python 脚本,如下所示:

        1. 仅使用importlib.import_module()动态加载模块
        2. 使用 getattr() 动态加载模块和类。

        备选方案 1

        如果您只想动态加载模块,请使用importlib.import_module()。假设您在子文件夹 protocols 中有以下协议:

        protocols/protocol_1.py 包含以下类:

        class Protocol():
            # some protocol specific code
        

        protocols/protocol_2.py 包含以下类:

        class Protocol():
            # some protocol specific code
        

        首先,我们使用将从 Web API 返回的协议名称定义动态变量:

        module = 'protocols.protocol_1' 
        

        然后我们导入 importlib 并动态加载模块。协议类在两个文件中具有相同的类名,但协议特定代码。之后,我们用动态加载的 Protocol 实例化 api_protocol:

        import importlib
        
        Protocol = importlib.import_module(module).Protocol
        
        api_protocol = Protocol()
        

        备选方案 2

        如果您还想动态加载类,请使用 getattr。假设您在子文件夹 protocols 中有以下协议:

        protocols/protocol_1.py 包含以下类:

        class Protocol_1():
            # some protocol specific code
        

        protocols/protocol_2.py 包含以下类:

        class Protocol_2():
            # some protocol specific code
        

        首先,我们使用将从 Web API 返回的协议名称来定义动态变量:

        module = 'protocols.protocol_1' 
        class_name = 'Protocol_1'
        

        然后我们调用__import__ 函数来动态加载动态模块。之后我们可以使用getattr 创建新类,并使用动态加载的协议实例化 api_protocol:

        mod = __import__(module, fromlist=[class_name])
        Protocol = getattr(mod, class_name)
        api_protocol = Protocol()
        

        【讨论】:

          猜你喜欢
          • 2015-07-01
          • 1970-01-01
          • 2018-02-08
          • 1970-01-01
          • 1970-01-01
          • 2023-03-05
          • 1970-01-01
          • 2020-01-27
          • 2021-02-24
          相关资源
          最近更新 更多