动态加载一个类

huangapple go评论66阅读模式
英文:

Load a class dynamically

问题

以下是翻译好的部分,不包括代码:

我有一个在启动时动态添加模块的软件。
启动发生在我的Python程序启动之后,所以我无法使用普通的“import DynModule”导入模块,而必须在运行时进行此操作。

因此,我想要做类似于以下的事情:

def load_module():
    try:
        import site
        site.addsitedir(r"C:\Users\...")
        from DynModule import Foo
    except (ModuleNotFoundError, ImportError) as e:
        logger.error("无法导入动态模块")
		
        class AccessClass(Process):
            def __init__(self):
                Process.__init__(self)
                logger.info("占位符类实例")
			
            def do_something(self):
                logger.info("占位符执行某些操作")
    else:
        class AccessClass(Process):
            def __init__(self):
                Process.__init__(self)
                logger.info("正确的类实例,用于动态加载的模块")
			
            def do_something(self):
                logger.info("实际执行某些操作")

然后在主程序中执行以下操作:

def action_on_load(self):
    from loader import load_module, AccessClass
	
    load_module()
    self._access = AccessClass()
    self._access.do_something()  # 输出 "实际执行某些操作"

然而,由于AccessClass是在try-except子句内部定义的,因此我无法导入它。我该如何继续并使其正常工作?

英文:

I have a software that dynamically adds modules at startup.
The start happens after the start of my Python program, so I cannot import the modules with a normal "import DynModule", but have to do this during runtime.

Therefore I would like to do something like this:

def load_module():
    try:
        import site
        site.addsitedir(r"C:\Users\...")
        from DynModule import Foo
		
     except (ModuleNotFoundError, ImportError) as e:
        logger.error("Could not import the dynamic module")
		
		class AccessClass(Process):
			def __init__(self):
				Process.__init__(self)
				logger.info("Placeholder class instance")
			
			def do_something(self):
				logger.info("Placeholder does something")
				
    else:
        class AccessClass(Process):
			def __init__(self):
				Process.__init__(self)
				logger.info("The right class instance to use the dynamically loaded module")
			
			def do_something(self):
				logger.info("Actually does something")

And then do something like this in the main program:

def action_on_load(self):
	from loader import load_module, AccessClass
	
	load_module()
	self._access = AccessClass()
	self._access.do_something() # prints "Actually does something"

However, I cannot import AccessClass as it is defined inside the try-except clause.

How can I proceed and get this to work?

答案1

得分: 1

以下是您要翻译的内容:

问题不在于它在try语句中定义,而在于它在函数中定义,其中名称AccessClass是一个局部变量。您可以将名称声明为全局变量:

def load_module():
    global AccessClass
    ...

因为class语句就像是一个复杂的赋值语句:它定义了一个类,然后将其绑定到一个名称上。不过,请注意,该类直到您实际调用函数时才会分配给该名称。在您的主程序中,您需要编写类似于以下内容:

def action_on_load(self):
    import loader  # 还没有AccessClass

    loader.load_module()  # 现在loader.AccessClass已定义。
    self._access = loader.AccessClass()
    self._access.do_something() # 输出“实际执行某些操作”

或者,您可以简单地返回该类:

def load_module():
    ...

    return AccessClass


def action_on_load(self):
    from loader import load_module

    AccessClass = load_module()
    self._access = AccessClass()
    self._access.do_something() # 输出“实际执行某些操作”

注意:代码部分不需要翻译。

英文:

The problem isn't that its defined in the try statement, but that it's defined in the function, where the name AccessClass is a local variable. You can declare the name as global:

def load_module():
    global AccessClass
    ...

because a class statement is like a fancy assignment statement: it defines a class, then binds it to a name. Note, though, that the class won't be assigned to the name until you actually call the function. In your main program, you'd need to write something like

def action_on_load(self):
    import loader  # No AccessClass yet
    
    loader.load_module()  # Now loader.AccessClass is defined.
    self._access = loader.AccessClass()
    self._access.do_something() # prints "Actually does something"

Or, you can simply return the class:

def load_module():
    ...

    return AccessClass


def action_on_load(self):
    from loader import load_module
    
    AccessClass = load_module()
    self._access = AccessClass()
    self._access.do_something() # prints "Actually does something"

huangapple
  • 本文由 发表于 2023年2月14日 01:24:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439231.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定