RestrictedPython:从函数内部进行打印时获取打印输出

时间:2018-09-05 02:29:00

标签: python plone sandbox zope

我正在使用RestrictedPython(使用safeglobals['_print_'] = PrintCollectorcompile_restricted_exec / exec(compiled_code, safe_globals, locals))运行以下代码。

def foo():
    print 'bar'

print '123'
foo()

执行代码后,我可以通过保存locals.pop('_print')实例的PrintCollector获得打印输出,但仅适用于函数外部的print '123'语句。调试时,我看到正在创建PrintCollector的两个实例,大概是在使用print语句的两个上下文(模块级别和函数)中创建的。

但是,我找不到一种方法来访问在输入PrintCollector时创建的def foo()实例。 RestrictedPython的文档非常少,这就是为什么我在这里询问关于如何以RestrictedPython方式访问函数的打印输出的任何建议的原因。

示例:

from RestrictedPython import compile_restricted
from RestrictedPython.PrintCollector import PrintCollector

_print_ = PrintCollector

code_string = """
def foo():
    print 'bar'

print '123'
foo()
"""

loc = {'_print_': PrintCollector, '_getattr_': getattr}
compiled_code = compile_restricted(code_string, '<string>', 'exec')
exec(compiled_code, loc)
loc['_print']()

2 个答案:

答案 0 :(得分:1)

更新:这是不使用打印语句调试受限代码的方法:

from RestrictedPython import compile_restricted
from RestrictedPython.PrintCollector import PrintCollector

_print_ = PrintCollector

code_string = """
def foo():
    global debug_inner
    debug_inner = 'bar'

foo()
debug_outer = '123'
results = [debug_inner, debug_outer]
"""

compiled_code = compile_restricted(code_string, '<string>', 'exec')
exec(compiled_code)
print results

# Output should be:
# >>> ['bar', '123']

旧答案:

按照您给出的示例,该函数需要返回printed变量,并且还必须在打印语句中执行,如以下文档所述: https://code.activestate.com/pypm/restrictedpython/#print

示例:

from RestrictedPython import compile_restricted
from RestrictedPython.PrintCollector import PrintCollector


_print_ = PrintCollector

code_string = """

def hello_world():
    print 'Hello inner world!'
    return printed

print 'Hello outer world!' # print a string

print hello_world()        # print return of function

results = printed          # fetch printed in a global

"""

# Compile and excecute restricted code:
compiled_code = compile_restricted(code_string, '<string>', 'exec')
exec(compiled_code)

# Now we have `results` available as a global:
print results.split('\n') # convert string into list of lines

# We should get:
# >>> ['Hello inner world!', 'Hello outer world!', '', '']

答案 1 :(得分:0)

我遇到了同样的问题,并且发现也创建了两个PrintCollector实例。

因此,我继承了类PrintCollector并将其设为单例。问题解决了。

def singleton(cls):
    _instance = {}
    def inner(t):
        if cls not in _instance:
            _instance[cls] = cls(t)
        return _instance[cls]
    return inner

@singleton
class SafePrintCollector(PrintCollector):
    pass

但是,如果要多次运行RestrictedPython,则需要添加一个reset方法来清除最后的打印输出。