用exec()

时间:2017-12-01 11:49:07

标签: python python-3.x

我在python中实现了一个简单的测试平台。

测试运行器向测试公开一组函数。 这可以被视为用于编写测试的领域特定语言。 大多数测试用例形成对这些函数的简单调用序列,有时涉及控制流语句,但没有比这更复杂。

现在,一些测试用例变得过于复杂,并且会因使用函数进行重构而受益。 这是我遇到问题的地方。 在函数内部,我无法访问测试用例中定义的局部符号。我也无法访问跑步者公开的功能(记录和验证)。

''' Testing variable scopes in exec()'''

PRG_1 = '''
a = 42
log('Testing a = ' + str(a))
verify(a, 42)
'''

PRG_2 = '''
a = 42
def f():
    c = a  # Error 'a' not defined
    log(c) # Error 'log' not defined

f()
'''

class TestRunner():
    def __init__(self, prg):
        self.prg = prg

    def log(self, msg):
        print(msg)

    def verify(self, a, b):
        print('PASSED' if a == b else 'FAILED')

    def run(self):
        # Bring methods into local scope to avoid having 'self.' in DSL
        log = self.log
        verify = self.verify

        # Execute test
        exec(self.prg)

r = TestRunner(PRG_1)
r.run()

r = TestRunner(PRG_2)
r.run()

关于如何让它发挥作用的任何想法? 也许有一种不同的(更好的方法)来实现这一点,我作为C ++开发人员看不到。

$ python3 test.py
Testing a = 42
PASSED
Traceback (most recent call last):
  File "test.py", line 42, in <module>
    r.run()
  File "test.py", line 35, in run
    exec(self.prg)
  File "<string>", line 7, in <module>
  File "<string>", line 4, in f
NameError: name 'a' is not defined

1 个答案:

答案 0 :(得分:2)

如果你这样做:

def run(self):
    exec(self.prg, {'log': self.log, 'verify': self.verify})

产地:

42

一般来说,最好避免像这样的动态代码执行!