重新加载使用*导入的包。

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

Reload package that was imported with *

问题

我有这个结构:

|-- handler
|   |-- __init__.py
|   |-- Layer1.py
|   |-- Layer2.py
|-- factory.py
|-- main.py

init.py 文件:

from os.path import dirname, basename, isfile, join
import glob

modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]

Layer 文件包括以下样式的类:

@ClassFactory.register(1)
class layer1:
    def __init__(self, string):
        self.do_something(string)

    def do_something(self, string):
        something...

在 main.py 文件中,我这样导入:

from handler import *

并调用注册表来运行类函数:

for key, value in sorted(ClassFactory.registry.items()):
    value("someValue")

我已经尝试了数小时来在主文件中重新加载 handler 包中的文件。我的目标是能够在解释器仍在运行时手动更改这些文件,然后重新加载它们。我尝试了许多方法,但似乎重新加载 importlib 不会重新加载 handler 中的模块。Ipython.lib 的 deepreload 失败,抛出 NotImplementedError。我无法理解我做错了什么。当我这样做时:

from handler import Layer1

我能够重新加载 Layer1,没有任何问题,但由于我在动态加载目录中加载所有内容,这对我没有帮助,而且必须使用 *。此外,我相当确定,从注册表中加载类会增加另一层复杂性,因为类必须重新注册自己。

感谢您的帮助。

英文:

I have this structure:

|-- handler
|   |-- __init__.py
|   |-- Layer1.py
|   |-- Layer2.py
|-- factory.py
|-- main.py

init.py file:

from os.path import dirname, basename, isfile, join
import glob

modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]

Layer file includes class that looks as follows:

@ClassFactory.register(1)
class layer1:
    def __init__(self,string):
        self.do_something(string)


    def do_something(self, string):
        something...

and in main.py file I import as follows:

from handler import *

And calls the registry to run the class function:

    for key, value in sorted(ClassFactory.registry.items()):
        value("someValue")

I've been trying for hours to make it reload the files in handler package in main. My goal is to be able to change the files manually and then reload them while the interpreter is still running.
I tried many things, reload of importlib doesn't seem to reload the modules in handler. deepreload of Ipython.lib fails with NotImplementedError. I can't understand what am I doing wrong. When I did:

from handler import Layer1

I was able to reload Layer1 without any issue, but since I'm loading everything in the directory dynamically, it doesn't help and it has to be with *.
Also, I'm pretty sure that the fact that I'm loading the classes from registry adds another layer of complication, since the classes have to re-register themselves.

Would appreciate your help

答案1

得分: 1

代替:

from handler import *

考虑使用类似以下方式:

import inspect, importlib

def import_from(module, dest = None):
    if dest is None:
        dest = globals()
    if hasattr(module, '__all__'):
        for item in module.__all__:
            dest[item] = getattr(module, item)
        return
    for name, value in inspect.getmembers(module):
        if name.startswith('_'):
            continue
        dest[name] = value

用法:

import handler
import_from(handler)

### ...and later...
handler = importlib.reload(handler)
import_from(handler)

如果从不同的模块中使用import_from助手,您需要将该模块的globals()传递给dest参数。

英文:

Instead of:

from handler import *

Consider something more like:

import inspect, importlib

def import_from(module, dest = None):
    if dest is None:
        dest = globals()
    if hasattr(module, '__all__'):
        for item in module.__all__:
            dest[item] = getattr(module, item)
        return
    for name, value in inspect.getmembers(module):
        if name.startswith('_'):
            continue
        dest[name] = value

Used as:

import handler
import_from(handler)

### ...and later...
handler = importlib.reload(handler)
import_from(handler)

If the import_from helper is used from a different module, you'll want to pass in that module's globals() as the dest argument.

答案2

得分: 1

我最终找到了一个简单的解决方案:

导入部分如下:

import handler
from handler import *

而为了重新加载,我执行了以下操作:

ClassFactory.registry.clear()

for i in handler.__all__:
    reload(globals()[i])

这只是简单地访问全局中位于handler包中的所有类名,并在循环中重新加载它们。

英文:

I ended up finding a simple solution:

Imports are

import handler
from handler import *

and for reload I did:

ClassFactory.registry.clear()

for i in handler.__all__:
    reload(globals()[i])

Which is simply accesses all the class names in global that are located in handler package and reload them in a loop.

huangapple
  • 本文由 发表于 2023年7月10日 21:25:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654217.html
匿名

发表评论

匿名网友

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

确定