python - 动态创建类时出现 Python 错误
问题描述
让我们看一个具有这种文件夹结构的项目:
> eval
> a
> __init__.py
> a.py
> b
> __init__.py
> b.py
__init__.py
__init__.py
m.py
文件夹__init__.py
中的内容:
from eval.a.a import A
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)
b__init__.py
文件夹中的内容:
from eval.b.b import B
b.py的内容:
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)
eval__init__.py
文件夹中的内容:
from eval.a.a import A
from eval.b.b import B
__init__.py
外部eval文件夹里面什么都没有。
m.py的内容:
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,为什么我的类 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())
因此,我将动态导入应用程序中定义的所有类。
推荐阅读
- c++ - target_include_directories cmake 如何包含本地库 如何工作
- php - XAMPP 虚拟主机 - 错误 403 访问被拒绝
- azure-devops - 如何使用 Azure Devops Pipelines 构建包含 x86 和 ARM 构建的 appxpackage?
- html - 如何将 svg 文件上传到 django 应用程序?
- assembly - MIPS 如果循环大于或等于
- python - 需要将图像掩码(多边形)输入网格并获得多边形覆盖的网格混合的百分比
- java - Spring Batch中如何读取多个CSV文件合并数据进行处理?
- android - 在我在 Flutter 中打开 Google Photos 之前,Multi Image Picker 无法找到我的图片
- html - 更改多选文本“x 项”
- java - 为什么会出现空对象引用错误?