I have an app written in python. I want to give my users the ability to manipulate the apps objects by allowing them to run their own scripts. They are likely to make errors in their scripts. If there is an error I want to ensure that the app doesn't stop running. I'd like to embed a debugger in my app to help them debug their scripts.
e.g. I define a point class in my app in shapes.py:
class QVPoint(object):
def __init__(self, x, y):
self.x = x
self.y = y
def addPoint(self, aPoint):
self.x = self.x + aPoint.x
self.y = self.y + aPoint.y
I want to enable them to run scripts like:
from shapes import QVPoint
a = QVPoint(1,1)
a.addPoint(QVPoint(2,2))
print "<" + str(a.x) + ',' + str(a.y) + ">"
print "<%d,%d>" % (a.x, a.y)
print 'done'
I figure this must use the interpreter, the debugger but I'm not sure on two counts, 1) how to expose objects that are created in the App to the script, and 2) how to ensure that the app doesn't stop if a bug causes the script to stop.
I'm sure this must have been asked before but I can't find it. All answers welcome.
Many thx
David
-
Format your code please.alternative– alternative2010年06月11日 18:00:04 +00:00Commented Jun 11, 2010 at 18:00
-
Just to clarify I want to share the app's state with the script. A sub-process would involve devising a protocol to communicate app state changes and would be very slow. The only thing that might be needed on a seperate thread would be a debugger on occasion - though I might be able to use a remote debugger.DangerMouse– DangerMouse2010年06月17日 10:15:24 +00:00Commented Jun 17, 2010 at 10:15
-
I think my solution will be to use compile() and eval() wrapped by try:except. using the globals of a blank module called sandbox.DangerMouse– DangerMouse2010年06月17日 11:26:41 +00:00Commented Jun 17, 2010 at 11:26
2 Answers 2
I would suggest you use a separate interpreter instance (separate python process) to evaluate user's scripts. This will guarantee that whatever breaks in the user script would never affect you application. You can run external processes using os module, this would be one way to do so: http://docs.python.org/library/os.html#os.popen
You can allow user's scripts to import certain module(s) from your application so that the variables you define are accessible by the scripts.
2 Comments
subprocess is recommended over os for starting external processes.There are a few decisions to be made.
Do you want to run it in the same process of your app or in a separate process?
Without knowing much detail of your app, I'd tend to favor running them in a separate process. Use the
subprocessmodule for this. You can create an app launcher that in turn calls your users script. If it throws an exception you can catch it and format the result and report back to the user.Do you want to expose the classes to your user or the objects to your user?
In your example, it seems sharing the classes is enough. This should be fairly simple.
If it is only classes, you can simply include it in the PYTHONPATH. Then your user can just import them. If you want to expose an object, it may requires you to do this in process. Or otherwise you have to find a way to serialize you objects and transfer it to the new process.