Greg Ewing <greg.ew...@canterbury.ac.nz> writes: > On 16/08/21 1:50 am, Hope Rouselle wrote: >> By the way, I'm aware that what I'm doing here is totally unsafe and I >> could get my system destroyed. I'm not planning on using this --- thank >> you for your concern. I'm just interested in understanding more about >> modules. > > Okay, I'll assume all the security issues have been taken are of, e.g. > by running all of this in a virtual machine...
Oh, good idea. :-D >> Notice how student m0 (who really scored a zero) >> first gets his grade right, but if I invoke it again, then it gets 50.0. > > The best way to do this would be to run each student's file in > a separate process, so you know you're getting a completely fresh > start each time. Yes, that would be much better indeed, but I'd be left with IPC mechanisms of exchanging data. My first idea is to just print out a JSON of the final report to be read by the grader-process. (That is essentially what I'm already doing, except that I don't need to serialize things in a string.) > The second best way would be to not use import_module, but to > exec() the student's code. That way you don't create an entry in > sys.modules and don't have to worry about somehow unloading the > module. > > Something like > > code = read_student_file(student_name) > env = {} # A dict to hold the student's module-level definitions > exec(code, env) > grade_question1(env) > env['procedure_x'] = key.procedure_x > grade_question2(env) > ...etc... That seems a lot easier to implement. >> That's not the whole problem. For reasons I don't understand, new >> modules I load --- that is, different students --- get mixed with these >> modifications in m0 that I made at some point in my code. > > I would have to see a specific example of that. I'm sorry. I don't think I was right in that observation. I tried to produce one such small program to post here and failed. (Let's forget about that.) > One thing to keep in mind is that if key.procedure_x modifies any > globals in the key module, it will still modify globals in the key > module -- not the student's module -- after being transplanted there. > > More generally, there are countless ways that a student's code > could modify something outside of its own module and affect the > behaviour of other student's code. This is why it would be > vastly preferable to run each test in a fresh process. I'm totally convinced. I'll do everything in a fresh process. Having guarantees makes the job much more pleasant to do. >> (*) If it were easy to unload modules... > > It's sometimes possible to unload and reimport a module, but > only if the module's effects are completely self-contained. > That depends not only on what the module itself does, but > what other modules do with it. If any other module has imported > it, that module will still contain references to the old > module; if there are instances of a class defined in it still > existing, they will still be instances of the old version of > the class; etc. > > 99.999% of the time it's easier to just start again with a > fresh Python process. I'm totally convinced. Thank you so much! -- https://mail.python.org/mailman/listinfo/python-list