"Another option I was thinking about for this purpose is parsing the python to make sure they don't get up to anything fishy."
If that was safe, it would have been bundled up into a module. This is a Frequently Asked Question for Python, and the answer is, you can't.
I thought of process separation, but it won't work. The best performance would be one persistent process that runs the cell computations, but it's too easy for Python code to find places to hide data persistently for communication above and beyond what you expect.
For example, would you have thought to block the following?
Python 2.4.3 (...)
Type "help", ...
>>> def f():
... f.i = f.i + 1
... print f.i
...
>>> f.i = 1
>>> f()
2
>>> f()
3
The people who know the most about Python, including the implementors, have said this impossible. Again, unless someone familiar with the community pops up and says something has changed in the several years since I was hanging out on comp.lang.python. But I doubt it.
And mind you, that's one example, and not a very sophisticated one. If you're answer was "no", or indeed anything other than "duh, of course, I've known about that for years", then you don't stand a chance at the sophisticated stuff.
You can't fork at cell-run-time, because while a process couldn't write anything back out to the parent, it could still grovel over the parent's data space which could still be used to advantage, and depending on the rest of your code may still make an out-of-band channel available.
You could fork a process per cell before anything "incriminating" has been instantiated in the parent process, but that's got a lot of problems even on one machine (including the 32K process limit), let alone a hosted service, and you'd still end up with the possibility of a "cell history" being recorded that could be potentially exploited.
Python does not give you the necessary primitives to accomplish this task. I see three options: Live with it (a viable option except online), spawn one process per team and officially bless that level of communication (though it radically changes the nature of the game), or change languages.
To be honest, Python is going to cause you other problems on your online server too, such as the extreme difficulty you're going to face in isolating Python functions to a certain amount of CPU time. (Same problem, as long as the Python code cooperates it might be possible (and it might not really) but if it starts hostilely modifying the parent code you lose.) Other languages have support for that too.
Unfortunately, you're really bashing on Python's weaknesses here.