6
\$\begingroup\$

I wrote the code for my undergraduate TA jobs, to check assignment codes of students in Python class are correct or not.

Usage of the code is

$ python [test01.py[,test02 , ...] answer.dat grade.md

It will write grades (range 0~100) to a file called grade.md.

"""
Testing Assginments
by kidkkr
03-16-2017
"""
import os
import sys
from difflib import SequenceMatcher
class ResultChecker:
 """ Check python code result with answer data """
 __slots__ = '_srcFiles', '_ansFile', '_gradeFile', '_grade', '_ans'
 def __init__(self, srcFiles, ansFile, gradeFile):
 self._srcFiles = srcFiles 
 self._ansFile = ansFile 
 self._ans = open(self._ansFile, 'r').read()
 self._gradeFile = gradeFile
 self._grade = "# Grade File\n"
 def _run_code(self, src):
 print('-----------running ' + src + '..-----------')
 os.system('python ' + src + ' > result.swp')
 res = open('./result.swp', 'r').read()
 ratio = int(SequenceMatcher(None, res, self._ans).ratio() * 100)
 self._grade += src + ' ' + str(ratio) + '\n'
 print('result: ' + str(ratio))
 def check(self):
 for src in self._srcFiles:
 self._run_code(src)
 open(self._gradeFile, 'w').write(self._grade) # Write _grade to a file
 print('Checking has completed.')
 print(self._gradeFile + ":")
 print(self._grade)
def __main__():
 if len(sys.argv) < 2: # Check arguments
 raise ValueError('')
 srcFiles = sys.argv[1:-2]
 ansFile = sys.argv[-2]
 gradeFile = sys.argv[-1]
 ResultChecker(srcFiles, ansFile, gradeFile).check()
if __name__ == '__main__':
 __main__() 
200_success
146k22 gold badges190 silver badges479 bronze badges
asked Mar 16, 2017 at 5:18
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Note that you should make sure you're being safe with untrusted scripts. Even if they're not malicious a student could break things that could cause future tests to fail or bigger problems. You should sandbox each run, either using something from here wiki.python.org/moin/Asking%20for%20Help/… or simply using a vm \$\endgroup\$ Commented Mar 16, 2017 at 11:45
  • \$\begingroup\$ I could not reached to that. It will be possible because I run codes directly in my shell.. Thank you for the advice! \$\endgroup\$ Commented Mar 16, 2017 at 19:33

1 Answer 1

6
\$\begingroup\$

Here is something I would improve:

  • fix the variable naming - according to PEP8, use lower case and separate words with an underscore - e.g. _grade_file instead of _gradeFile
  • use argparse module instead of manually reading from sys.argv - you will get the auto-generated command-line help for free and it is generally more readable, structured and scalable. As a bonus, you may avoid checking the length of the sys.argv and reading the "files" into variables. Something along these lines:

    import argparse
    def parse_arguments():
     parser = argparse.ArgumentParser()
     parser.add_argument('--source-files', nargs="+", type=str)
     parser.add_argument('--answer-file', type=argparse.FileType('r'))
     parser.add_argument('--grade-file', type=argparse.FileType('w'))
     return parser.parse_args()
    

    Note the use of the special FileType argument type.

    And, because of the use of nargs="+", you should change the way you pass python file names - instead of a comma-separated list, use space:

    $ python --source-files test01.py test02.py --answer-file answer.dat --grade-file grade.md
    
  • use with context manager when opening files

  • try subprocess.Popen() instead of os.system() - with "popen" you may not need to temporarily write the result to a swap file and read the standard out and error directly
  • I understand that an underscore at the beginning of a variable name is a convention to mark "private variables", but, if the checker class would not be a part of a public-facing API, it would be okay to remove the underscores to improve on readability
answered Mar 16, 2017 at 5:34
\$\endgroup\$
1
  • \$\begingroup\$ argparse module is cool. I hope I used to PEP8.. Thank you :) \$\endgroup\$ Commented Mar 16, 2017 at 19:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.