on perhaps unloading modules?
Hope Rouselle
hrouselle at jevedi.com
Mon Aug 16 07:47:09 EDT 2021
Greg Ewing <greg.ewing at 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!
More information about the Python-list
mailing list