2013-02-24 24 views
0

我期待在Codeacademy上撰写基础生物信息学课程。他们有一个很好的编写课程的界面,但测试有点慢,因为必须保存,然后预览,然后运行。如何获取由exec加载的任意变量,并在函数中使用它们

所以我想写一个模拟他们的小测试环境。它的工作原理是将用户输入的代码作为字符串读入到函数中,代码中的所有str实例都被转换为unicode(我刚刚使用过正则表达式),然后使用exec

棘手的部分似乎是当我想要合并Submission Test

提交测试需要返回True,Falsestr,并写成函数的主体。因此,例如:

的什么,我希望做一个简化版本:

# The submission test must be a function. 
def test_code(code, CC, error): 
    # Use information from errors in student code 
    if error: 
     return "Yada yada %s" %error 

    # Use information in the raw student code 
    if len(code.split("\n")) is not 2: 
     return "This should be accomplished in 2 lines" 

    # Have direct access to variables from the student code 
    # I'd like to avoid params['y'] if possible. 
    try: 
     y 
    except NameError: 
     return "Please use the variable y" 

    if y is not 8: 
     return "Wrong! Check stuff" 

    # Use information from print output 
    if str(y) not in CC: 
     return "Remember to print your variable!" 

    return True 

# Read in student code 
student_code = """y = 8 
        print y 
        potato""" 

# Catch print output 
CC = StringIO.StringIO() 
sys.stdout = CC 

# Execute student code and catch errors 
try: 
    exec student_code 
except Exception as e: 
    error = e 

# Start outputting to the terminal again 
sys.stdout = sys.__stdout__ 

# Run the submission test 
submission_test = test_code(student_code, CC.split("\n"), error) 

# Output the result of the submission test 
if submission_test is True: 
    print("Well done!") 
elif submission_test is False: 
    print("Oops! You failed... Try again!") 
else: 
    print(submission_test) 

不过,我似乎无法从exec code获得通过变量传递给提交测试功能(test_code在这种情况下)。

我可以在提交测试中执行代码,但是如果可能的话我想避免这种情况,否则它将不得不被添加到每个测试中,这看起来好像没有问题!

任何帮助,将不胜感激:)

+0

您的代码已损坏。例如,提交可能包含诸如'code_check = None'之类的东西,并且在'submission_test = code_check(code,CC,error)'这一行''末尾处理'TypeError:'NoneType'对象不可调用。顺便说一下:使用'== True'和'== False'是检查对象真值的错误方法。只要'是submission_test:print(“传递”)...',或者使用'is'运算符。 – Bakuriu 2013-02-24 13:43:44

+0

感谢单挑Bakuriu。这仅用于内部测试。实际的实施在Codeacademy。我不确定他们的转轮功能是如何工作的。我只是想模仿他们的功能,但我不需要太担心我的跑步者功能的安全性。 虽然我会在'is'用法编辑:) – 2013-02-24 14:00:25

+0

你可以将提交的代码和提交的测试(作为字符串)连接成一个字符串,然后在其上运行'exec'? – unutbu 2013-02-24 14:12:48

回答

0

好了,我的同事想通这一个。

它使用Devin Jeanpierre的答案的元素。

我们使用exec code in dictionary方法,然后将字典传入检查函数,然后在检查函数中,我们将字典解压到globals()

# The submission test must be a function. 
def test_code(code, CC, error, code_vars): 

    # unpack the student code namespace into the globals() 
    globs = globals() 
    for var, val in code_vars.items(): 
     globs[var] = val 

    # Use information from errors in student code 
    if error: 
     return "Yada yada %s" %error 

    # Use information in the raw student code 
    if len(code.split("\n")) is not 2: 
     return "This should be accomplished in 2 lines" 

    # Have direct access to variables from the student code 
    # I'd like to avoid params['y'] if possible. 
    try: 
     y 
    except NameError: 
     return "Please use the variable y" 

    if y is not 8: 
     return "Wrong! Check stuff" 

    # Use information from print output 
    if str(y) not in CC: 
     return "Remember to print your variable!" 

    return True 

# Read in student code 
student_code = """y = 8 
        print y 
        potato""" 

# Catch print output 
CC = StringIO.StringIO() 
sys.stdout = CC 

# create the namespace for the student code 
code_vars = {} 

# Execute student code and catch errors 
try: 
    # execute the student code in the created namespace 
    exec student_code in code_vars 
except Exception as e: 
    error = e 

# Start outputting to the terminal again 
sys.stdout = sys.__stdout__ 

# Run the submission test 
submission_test = test_code(student_code, CC.split("\n"), error, code_vars) 

# Output the result of the submission test 
if submission_test is True: 
    print("Well done!") 
elif submission_test is False: 
    print("Oops! You failed... Try again!") 
else: 
    print(submission_test) 
2

如果exec mystr in somedict,然后somedict具有的mystr执行的Python代码时指定每个变量的引用。另外,你也可以用这种方式传递变量。

>>> d = {'y': 3} 
>>> exec "x = y" in d 
>>> d['x'] 
3 

您需要将您从运行的用户代码得到了词典,以便提交校验码可以验证值它是适当的。

+0

嗯,我真的希望能够在提交测试中调用变量而不是使用字典。这主要是为了让系统模仿Codeacademy系统,并允许在两者之间复制和粘贴代码而不用改变。 – 2013-02-24 13:34:13

1

这听起来像你想要codetest运行在相同的环境。两者都被提交为字符串,所以也许最简单的方法是连接两者,合并的字符串上运行exec

from __future__ import unicode_literals 

def wrap_body(body): 
    indent = ' '*4 
    return 'def test():\n' + indent + body.replace('\n','\n'+indent)  

code = ''' 
bool_1 = True 
bool_2 = False 

str_1 = 'Hello there!' 
str_2 = "I hope you've noticed the apostrophe ;)" 
''' 

code_test = ''' 
try: 
    bool_1, bool_2, str_1, str_2 
except NameError: 
    return "Please do not alter the variable names!" 

if (bool_1 == bool_2 or str_1 == str_2): 
    return "Please ensure that all of your variables are different " \ 
      "from one another" 

if type(bool_1) != bool: return "bool_1 is incorrect" 
if type(bool_2) != bool: return "bool_2 is incorrect" 
if type(str_1) != unicode: return "str_1 is incorrect" 
if type(str_2) != unicode: return "str_2 is incorrect" 

return True 
''' 
code_test = wrap_body(code_test) 
template = code + code_test 
namespace = {} 
try: 
    exec template in namespace 
    print(namespace['test']()) 
except Exception as err: 
    print(err) 
+0

这很好!不幸的是,无论学生有错误,我都需要运行提交测试,以便我可以返回有用的,针对具体问题的反馈。因为这是目前,我需要有通用的错误处理。我刚刚简化了我的问题代码,如果有帮助:) – 2013-02-25 04:18:16

相关问题