我希望在Codeacademy上写一篇基本的生物信息学课程。他们有一个很好的编写课程的界面,但测试有点慢,因为必须保存,然后预览,然后运行。
所以我想写一个模仿他们的测试环境。看起来如何工作是用户输入代码作为字符串读入函数,代码中的所有str
实例都转换为unicode
(我刚刚使用了正则表达式)然后用exec
执行代码。
当我想要合并Submission Test时,似乎很棘手。
提交测试需要返回True
,False
或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
)。
我可以在提交测试中执行代码,但是如果可能的话我想避免使用它,否则它将被添加到每个测试中,这似乎是单声道的!
非常感谢任何帮助:)
答案 0 :(得分:2)
如果您exec mystr in somedict
,那么somedict
会引用在执行mystr
期间指定的每个变量作为Python代码。此外,您也可以通过这种方式传递变量。
>>> d = {'y': 3}
>>> exec "x = y" in d
>>> d['x']
3
您需要传递运行用户代码的字典,以便提交检查代码可以验证其中的值是否合适。
答案 1 :(得分:1)
听起来您希望code
和test
在同一环境中运行。两者都是作为字符串提交的,所以最简单的方法是连接两者并在组合字符串上运行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)
答案 2 :(得分: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)