使用Pysandbox实现在线pythonshell

使用Pysandbox实现在线pythonshell,python,implementation,pysandbox,Python,Implementation,Pysandbox,我想构建一个类似Python的在线shell。目前我正在尝试构建一个模块 在Python中,哪个做了以下事情 创建一个新会话 运行作为字符串传递的代码,并维护当前会话的环境变量 我正试图用它来实现这个目标。这是我迄今为止的努力 from sandbox import Sandbox, SandboxConfig from optparse import OptionParser import sys,traceback class Runner: def __init__(self):

我想构建一个类似Python的在线shell。目前我正在尝试构建一个模块 在Python中,哪个做了以下事情

  • 创建一个新会话
  • 运行作为字符串传递的代码,并维护当前会话的环境变量
  • 我正试图用它来实现这个目标。这是我迄今为止的努力

    from sandbox import Sandbox, SandboxConfig
    from optparse import OptionParser
    import sys,traceback
    
    class Runner:
        def __init__(self):
            self.options = self.parseOptions()
            self.sandbox = Sandbox(self.createConfig())
            self.localvars = dict()
        def parseOptions(self):
            parser = OptionParser(usage="%prog [options]")
            SandboxConfig.createOptparseOptions(parser, default_timeout=None)
            parser.add_option("--debug",
                help="Debug mode",
                action="store_true", default=False)
            parser.add_option("--verbose", "-v",
                help="Verbose mode",
                action="store_true", default=False)
            parser.add_option("--quiet", "-q",
                help="Quiet mode",
                action="store_true", default=False)
            options, argv = parser.parse_args()
            if argv:
                parser.print_help()
                exit(1)
            if options.quiet:
                options.verbose = False
            return options
    
        def createConfig(self):
            config = SandboxConfig.fromOptparseOptions(self.options)
            config.enable('traceback')
            config.enable('stdin')
            config.enable('stdout')
            config.enable('stderr')
            config.enable('exit')
            config.enable('site')
            config.enable('encodings')
            config._builtins_whitelist.add('compile')
            config.allowModuleSourceCode('code')
            config.allowModule('sys',
                'api_version', 'version', 'hexversion')
            config.allowSafeModule('sys', 'version_info')
            if self.options.debug:
                config.allowModule('sys', '_getframe')
                config.allowSafeModule('_sandbox', '_test_crash')
                config.allowModuleSourceCode('sandbox')
            if not config.cpython_restricted:
                config.allowPath(__file__)
            return config
        def Run(self,code):
            # log and compile the statement up front
            try:
                #logging.info('Compiling and evaluating:\n%s' % statement)
                compiled = compile(code, '<string>', 'single')
            except:
                traceback.print_exc(file=sys.stdout)
                return
            try:
                self.sandbox.execute(code)
            except:
                traceback.print_exc(file=sys.stdout)
    
    def f():
        f = open('test.py')
        code = ''
        for lines in f:
            code = code+lines
        runner = Runner()
        runner.Run('a = 5')
        runner.Run('b = 5')
        runner.Run('print a+b')
    f()
    
  • 如何维护当前会话的环境?例如,在上面的代码序列中

    a=5
    b=5
    打印a+b

  • 结果应该是输出10。
    有什么想法吗?

    这应该行得通,不过您可能想处理异常的输出:

    from sandbox import Sandbox, SandboxConfig
    from optparse import OptionParser
    import sys,traceback
    
    class Runner:
        def __init__(self):
            self.options = self.parseOptions()
            self.sandbox = Sandbox(self.createConfig())
            self.localvars = dict()
            self.code = ''
        def parseOptions(self):
            parser = OptionParser(usage="%prog [options]")
            SandboxConfig.createOptparseOptions(parser)#, default_timeout=None)
            parser.add_option("--debug",
                help="Debug mode",
                action="store_true", default=False)
            parser.add_option("--verbose", "-v",
                help="Verbose mode",
                action="store_true", default=False)
            parser.add_option("--quiet", "-q",
                help="Quiet mode",
                action="store_true", default=False)
            options, argv = parser.parse_args()
            if argv:
                parser.print_help()
                exit(1)
            if options.quiet:
                options.verbose = False
            return options
    
        def createConfig(self):
            config = SandboxConfig.fromOptparseOptions(self.options)
            config.enable('traceback')
            config.enable('stdin')
            config.enable('stdout')
            config.enable('stderr')
            config.enable('exit')
            config.enable('site')
            config.enable('encodings')
            config._builtins_whitelist.add('compile')
            config.allowModuleSourceCode('code')
            config.allowModule('sys',
                'api_version', 'version', 'hexversion')
            config.allowSafeModule('sys', 'version_info')
            if self.options.debug:
                config.allowModule('sys', '_getframe')
                config.allowSafeModule('_sandbox', '_test_crash')
                config.allowModuleSourceCode('sandbox')
            if not config.cpython_restricted:
                config.allowPath(__file__)
            return config
        def Run(self,code):
            code = '\n'.join([self.code,code])
            # log and compile the statement up front
            try:
                #logging.info('Compiling and evaluating:\n%s' % statement)
                compiled = compile(code, '<string>', 'single')
            except:
                traceback.print_exc(file=sys.stdout)
                return
            try:
                self.sandbox.execute(code)
            except:
                err = sys.exc_info()[1]
                print type(err), err
            else:
                self.code = code
    
    def f():
        f = open('test.py')
        code = ''
        for lines in f:
            code = code+lines
        runner = Runner()
        runner.Run('a = 5')
        runner.Run('b = 5')
        runner.Run('print a+b')
    f()
    
    从沙盒导入沙盒,沙盒配置
    从optpasse导入OptionParser
    导入系统,回溯
    班级跑步者:
    定义初始化(自):
    self.options=self.parseOptions()
    self.sandbox=沙盒(self.createConfig())
    self.localvars=dict()
    self.code=“”
    def解析选项(自):
    parser=OptionParser(用法=“%prog[options]”)
    SandboxConfig.createOptparseOptions(解析器)#,默认值_timeout=None)
    parser.add_选项(“--debug”,
    help=“调试模式”,
    action=“store\u true”,默认值=False)
    添加_选项(“--verbose”,“-v”,
    help=“详细模式”,
    action=“store\u true”,默认值=False)
    添加_选项(“--quiet”、“-q”,
    help=“安静模式”,
    action=“store\u true”,默认值=False)
    选项,argv=parser.parse_args()
    如果argv:
    parser.print_help()
    出口(1)
    如果选项.quiet:
    options.verbose=False
    返回选项
    def createConfig(自身):
    config=SandboxConfig.fromOptparseOptions(self.options)
    config.enable('回溯')
    config.enable('stdin')
    config.enable('stdout')
    config.enable('stderr')
    config.enable('退出')
    config.enable('站点')
    config.enable('encodings')
    config.\u内置\u白名单.add('compile')
    config.allowModuleSourceCode('code'))
    config.allowModule('sys',
    ‘api_版本’、‘版本’、‘hexversion’)
    config.allowSafeModule('sys','version\u info')
    如果self.options.debug:
    config.allowModule('sys','u getframe'))
    config.allowSafeModule(“沙盒”、“测试”和“崩溃”)
    config.allowModuleSourceCode('sandbox')
    如果没有config.cpython\u限制:
    config.allowPath(_文件__)
    返回配置
    def运行(自身,代码):
    代码='\n'.join([self.code,code])
    #预先记录并编译语句
    尝试:
    #logging.info('编译和评估:\n%s'%1!'语句)
    compiled=compile(代码,,'single')
    除:
    traceback.print_exc(file=sys.stdout)
    返回
    尝试:
    self.sandbox.execute(代码)
    除:
    err=sys.exc_info()[1]
    打印类型(错误),错误
    其他:
    self.code=代码
    def():
    f=打开('test.py')
    代码=“”
    对于f中的行:
    代码=代码+行
    runner=runner()
    runner.Run('a=5')
    runner.Run('b=5')
    runner.Run('打印a+b')
    f()
    
    如果您想要保留已创建的会话(用于浏览器),请查看,虽然我不知道这是否正是您想要的,但我认为这是一个很好的建议。@ITNinja希望实现这个或python版本的tryhaskell.com此代码反复运行相同的代码。我希望执行像python解释器一样。如果您将“全局”和“局部”对象传递到您的Sandbox.execute(),我认为这将保存您希望它们保存的大部分内容。问题是如何获取这些“局部”和“gloabls”?首先,它们是
    {}
    。这些是可变对象,因此对execute()的调用将修改它们。你所要做的就是记住它们,比如
    self.locals
    self.globals
    ,并每次传递相同的对象。
    from sandbox import Sandbox, SandboxConfig
    from optparse import OptionParser
    import sys,traceback
    
    class Runner:
        def __init__(self):
            self.options = self.parseOptions()
            self.sandbox = Sandbox(self.createConfig())
            self.localvars = dict()
            self.code = ''
        def parseOptions(self):
            parser = OptionParser(usage="%prog [options]")
            SandboxConfig.createOptparseOptions(parser)#, default_timeout=None)
            parser.add_option("--debug",
                help="Debug mode",
                action="store_true", default=False)
            parser.add_option("--verbose", "-v",
                help="Verbose mode",
                action="store_true", default=False)
            parser.add_option("--quiet", "-q",
                help="Quiet mode",
                action="store_true", default=False)
            options, argv = parser.parse_args()
            if argv:
                parser.print_help()
                exit(1)
            if options.quiet:
                options.verbose = False
            return options
    
        def createConfig(self):
            config = SandboxConfig.fromOptparseOptions(self.options)
            config.enable('traceback')
            config.enable('stdin')
            config.enable('stdout')
            config.enable('stderr')
            config.enable('exit')
            config.enable('site')
            config.enable('encodings')
            config._builtins_whitelist.add('compile')
            config.allowModuleSourceCode('code')
            config.allowModule('sys',
                'api_version', 'version', 'hexversion')
            config.allowSafeModule('sys', 'version_info')
            if self.options.debug:
                config.allowModule('sys', '_getframe')
                config.allowSafeModule('_sandbox', '_test_crash')
                config.allowModuleSourceCode('sandbox')
            if not config.cpython_restricted:
                config.allowPath(__file__)
            return config
        def Run(self,code):
            code = '\n'.join([self.code,code])
            # log and compile the statement up front
            try:
                #logging.info('Compiling and evaluating:\n%s' % statement)
                compiled = compile(code, '<string>', 'single')
            except:
                traceback.print_exc(file=sys.stdout)
                return
            try:
                self.sandbox.execute(code)
            except:
                err = sys.exc_info()[1]
                print type(err), err
            else:
                self.code = code
    
    def f():
        f = open('test.py')
        code = ''
        for lines in f:
            code = code+lines
        runner = Runner()
        runner.Run('a = 5')
        runner.Run('b = 5')
        runner.Run('print a+b')
    f()