为什么python eval()可以访问导入的函数,但不能访问类



我有一个定义类和函数的模块:

#barbaz.py
class Bar:
pass
def baz():
return "hello"

在另一个模块中,我有一个带有eval语句的函数:

#foo.py (version 1)
def foo(baz: callable):
bazstr: str = baz.__name__
print(bazstr)
try:
f=eval(f'{bazstr}()')
print(f'result: {f}')
except Exception as e:
print(f"eval error: {e}")

最后,我在另一个模块中进行了测试:

#test.py
from evalf import foo
from barbaz import baz, Bar
#This works...
foo(baz)
#This doesn't
foo(Bar)

baz有效,但Bar无效。我得到输出:

baz
result: hello
Bar
eval error: name 'Bar' is not defined

eval似乎无法使用从模块导入的类,除非它与foo()函数直接导入到同一模块中。也就是说,这是有效的:

#foo.py (version 2)
from barbaz import Bar
def foo(baz: callable):
bazstr: str = baz.__name__
print(bazstr)
try:
f=eval(f'{bazstr}()')
print(f'result: {f}')
except Exception as e:
print(f"eval error: {e}")
foo(Bar)

为什么foo.py的版本2可以工作,而版本1抛出了所示的错误?

如何绕过这一点,并在eval语句中使用导入的类,该语句位于它自己的模块中?

foo.py无法按预期工作,因为它在全局命名空间中没有函数(eval在此处查找本地范围中找不到的名称(。它对函数有效,因为完全巧合的是,外部函数(baz(和参数名称(baz(是相同的。它根本没有看到def baz函数,而是看到了您命名的参数(巧合的是(baz

解决方案是只使用您无条件收到的参数的名称;如果必须使用eval,只需将其中可调用的名称硬编码为baz,因为它在本地作用域中总是被称为。您可能不应该使用eval(在您的代码中,f = baz()可以很好地完成这项工作(,但如果必须使用,那就是解决方案。

问题是foo函数中有baz,而没有Bar

def foo(baz: callable):
bazstr: str = baz.__name__
print(bazstr)
try:
f = eval(f'{bazstr}()')
print(f'result: {f}')
except Exception as e:
print(f"eval error: {e}")

使用eval是危险的,您可以简单地在可调用参数旁边添加()。我把你的三个文件中的代码放在一个文件中,因为单独的文件不会改变它的作用:

class Bar:
pass
def baz():
return "hello"
def foo(baz: callable):
try:
f = baz()
print(f'result: {f}')
except Exception as e:
print("Not callable.")
foo(baz)
foo(Bar)

输出:

result: hello
result: <__main__.Bar object at 0x0000020EA3496E48>

相关内容

  • 没有找到相关文章

最新更新