动态创建类时出现Python错误

动态创建类时出现Python错误,python,class,dynamic,eval,creation,Python,Class,Dynamic,Eval,Creation,让我们以具有此文件夹结构的项目为例: > eval > a > __init__.py > a.py > b > __init__.py > b.py __init__.py __init__.py m.py \uuuu init\uuuuuu.py文件夹中的内容: from eval.a.a import A from eval.b.b import B from eval.a.a import A f

让我们以具有此文件夹结构的项目为例:

> eval
  > a
    > __init__.py
    > a.py
  > b
    > __init__.py
    > b.py
  __init__.py
__init__.py
m.py
\uuuu init\uuuuuu.py
文件夹中的内容:

from eval.a.a import A
from eval.b.b import B
from eval.a.a import A
from eval.b.b import B
a.py的内容

class A:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class A"

    def __str__(self) -> str:
        return "Class A"

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
class B:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class B"

    def __str__(self) -> str:
        return "Class B "

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
from eval.a import A
from eval.b import B

a = eval('A()');
print(a)

b = eval('B()');
print(b)
\uuuu init\uuuuu.py
b文件夹中的内容:

from eval.a.a import A
from eval.b.b import B
from eval.a.a import A
from eval.b.b import B
b.py的内容

class A:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class A"

    def __str__(self) -> str:
        return "Class A"

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
class B:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class B"

    def __str__(self) -> str:
        return "Class B "

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
from eval.a import A
from eval.b import B

a = eval('A()');
print(a)

b = eval('B()');
print(b)
eval文件夹中的
\uuuu init\uuuuuuuuuuuuuuupy
内容:

from eval.a.a import A
from eval.b.b import B
from eval.a.a import A
from eval.b.b import B
\uuuu init\uuuuu.py
外部eval文件夹内部没有任何内容

m.py的内容

class A:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class A"

    def __str__(self) -> str:
        return "Class A"

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
class B:
    def __init__(self) -> None:
        pass

    def __repr__(self) -> str:
        return "Class B"

    def __str__(self) -> str:
        return "Class B "

    def exec(self):
        a = eval('A()');
        print(a)

        b = eval('B()');
        print(b)
from eval.a import A
from eval.b import B

a = eval('A()');
print(a)

b = eval('B()');
print(b)
到目前为止,它还可以工作,创建我的A()和B()对象,打印:

Class A
Class B
但是如果我将m.py更改为:

from eval.a import A
from eval.b import B

a = eval('A()');
print(a)

b = eval('B()');
print(b)

print('Running A.exec() now:')
a.exec()

print('Running B.exec() now:')
b.exec()
然后我会得到:

Class A
Class B 
Running A.exec() now:
Class A
Traceback (most recent call last):
  File "c:\dev\test\python\teste_eval\m.py", line 19, in <module>
    a.exec()
  File "c:\dev\test\python\teste_eval\eval\a\a.py", line 15, in exec
    b = eval('B()');
  File "<string>", line 1, in <module>
NameError: name 'B' is not defined
A类
B类
现在运行A.exec():
甲级
回溯(最近一次呼叫最后一次):
文件“c:\dev\test\python\teste\u eval\m.py”,第19行,在
a、 行政长官()
文件“c:\dev\test\python\teste\u eval\eval\a\a.py”,第15行,在exec中
b=评估('b()');
文件“”,第1行,在
名称错误:未定义名称“B”
那么问题是:


  • 如果在我创建类的文件中同时导入了类A和类B,为什么我的类B对我的A.exec()不可用

  • 如何修复它?是什么意思使我的系统中的任何类都可以由任何类创建,即使是在单独的模块中(如本例中的“eval”模块)

  • 有比使用eval函数更好的动态创建这些类的方法吗


  • 感谢您的支持。

    我刚刚找到了一种加载所有模块的方法

    这是一个可能的解决方案:

    import sys
    
    def get_user_modules() -> list:
        ret = []
        sm = sys.modules
        for k in sm.keys():
            if (k[0] != '_'):
                if (not k.startswith('encodings.')):
                    if (not (k in ['sys', 'builtins', 'nt', 'marshal', 'winreg', 'time', 'zipimport', 'codecs', 
                                'encodings', 'abc', 'io', 'stat', 'genericpath', 'ntpath', 'os', 'site', 'os.path'])):
                        ret.append(k)
        return ret
    
    此代码将返回:

    ['eval.a.a', 'eval.a', 'eval.b.b', 'eval.b', 'eval']
    
    对于示例中使用的系统结构

    我认为最终的解决方案应该基于加载的模块列表

    感谢每一个试图帮助我的人

    更新:

    另一种可能是从起点到最后一个文件夹遍历文件系统,如下所示:

    def get_all_modules() -> list:
        r = os.path.dirname(sys.argv[0])
        t = len(r)
        l = []
        for root, dirs, files in os.walk(r):
            s = root[t:].replace('\\', '.')
            for f in files:
                if (f.endswith('.py') and (f[0:2] != '__')):
                    fn = f[:-3]
                    if (s != ''):
                        fn = s[1:] + '.' + fn
                    l.append(fn)
        return l
    
    然后,我可以使用:

    def import_all_modules() -> str:
        um = get_all_modules()
        s  = ''
        for k in um:
            if (k != __name__):
                s = s + f'from {k} import *\n'
        return s
    
    要获取导入和执行此操作所需的所有信息,请执行以下操作:

    exec(import_all_modules())
    

    因此,我将动态导入应用程序中定义的所有类。

    仅仅因为名称
    B
    存在于某些模块中并不意味着它无处不在。Python没有全局名称空间,每个模块都有自己的名称空间
    eval
    在代码中没有任何有用的用途,因此很难理解您想要做什么,而仅仅删除eval并将源代码直接放入
    .py
    文件中是做不到的,而不是作为字符串传递给
    eval
    还要注意,您不是在创建类,而是在创建这些类的实例“如果我在创建类的文件中同时导入了类A和类B,为什么我的类B对我的A.exec()不可用?“因为这无关紧要,所以名称必须在使用的地方可用。您似乎假设作用域是动态工作的,但事实并非如此。python使用词汇作用域,而不是动态作用域。那么您就有点为难了,因为python在这里的行为与其他语言有所不同。每个模块都需要显式导入它需要访问的名称。没有全局共享的名称空间。现在,最后一个疑问!如何使用此列表强制导入?我尝试使用
    eval(s)
    ,其中s是一个字符串,包含来自eval的
    。导入*
    ,但它不起作用。有人知道我如何在运行时创建导入命令吗?谢谢。没关系,解决了!