0

我希望在Codeacademy上写一门基本的生物信息学课程。他们有一个很好的编写课程的界面,但是测试有点慢,因为必须保存,然后预览,然后运行。

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

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

提交测试需要返回True, False, 或 a str, 并且被写成函数的主体。例如:

我想要做的简化版本:

# 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在这种情况下)。

我可以在提交测试中执行代码,但如果可能的话,我想避免这种情况,否则必须将它添加到每个测试中,这看起来很不合python!

任何帮助将不胜感激 :)

4

3 回答 3

2

如果你exec mystr in somedict,那么在作为 Python 代码somedict执行期间分配的每个变量都有一个引用。mystr此外,您也可以通过这种方式传递变量。

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

您需要传递从运行用户代码中获得的字典,以便提交检查代码可以验证其中的值是否合适。

于 2013-02-24T13:28:58.023 回答
1

听起来您希望 thecode和 thetest在同一环境中运行。两者都作为字符串提交,所以也许最简单的方法是将两者连接起来并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)
于 2013-02-24T14:45:04.853 回答
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)
于 2013-02-25T04:50:11.670 回答