我正在尝试创建一种从普通(非沙盒)cPython 或 PyPy 脚本中与沙盒 PyPy 解释器交互的方法。
我已经能够按照这些说明http://doc.pypy.org/en/latest/sandbox.html编译沙盒化 PyPy 解释器,并且我有一个 pypy-c-sandbox 文件,它与 pypy_interact.py 一起创建一个交互式沙盒解释器。
现在我想做一个非常相似的事情,但是我不想使用 stdin/stdout 作为我的 io,而是想使用 python 脚本与 pypy-sandbox 进程进行交互。我已经得到了这个工作的大部分。我可以使用带有 cStringIO 对象的 .communicate() 函数作为输入、输出和错误,并从普通 python 访问这些数据。
但是,这是我的问题,当我在同一个实例化的 PyPy 沙箱对象上第二次调用 .communicate() 时,我什么也得不到。它只是第一个 .communicate 作品。我很困惑为什么会出现这种情况以及如何解决它。
我拼凑了一个丑陋的黑客来证明我的问题:
import sys, os
import autopath
from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc
from pypy.translator.sandbox.sandlib import VirtualizedSandboxedProc
from pypy.translator.sandbox.vfs import Dir, RealDir, RealFile
import pypy
LIB_ROOT = os.path.dirname(os.path.dirname(pypy.__file__))
class PyPySandboxedProc(VirtualizedSandboxedProc, SimpleIOSandboxedProc):
argv0 = '/bin/pypy-c'
virtual_cwd = '/tmp'
virtual_env = {}
virtual_console_isatty = True
arguments = ['../goal/pypy-c', '-u']
def __init__(self, executable, arguments, tmpdir=None, debug=True):
self.executable = executable = os.path.abspath(executable)
self.tmpdir = tmpdir
self.debug = debug
super(PyPySandboxedProc, self).__init__([self.argv0] + arguments,
executable=executable)
def build_virtual_root(self):
# build a virtual file system:
# * can access its own executable
# * can access the pure Python libraries
# * can access the temporary usession directory as /tmp
exclude = ['.pyc', '.pyo']
if self.tmpdir is None:
tmpdirnode = Dir({})
else:
tmpdirnode = RealDir(self.tmpdir, exclude=exclude)
libroot = str(LIB_ROOT)
return Dir({
'bin': Dir({
'pypy-c': RealFile(self.executable),
'lib-python': RealDir(os.path.join(libroot, 'lib-python'),
exclude=exclude),
'lib_pypy': RealDir(os.path.join(libroot, 'lib_pypy'),
exclude=exclude),
}),
'tmp': tmpdirnode,
})
# run test
arguments = ['../goal/pypy-c', '-u']
sandproc = PyPySandboxedProc(arguments[0], arguments[1:],
tmpdir=None, debug=True)
#start the proc
code1 = "print 'started'\na = 5\nprint a"
code2 = "b = a\nprint b\nprint 'code 2 was run'"
output, error = sandproc.communicate(code1)
print "output: %s\n error: %s\n" % (output, error)
output, error = sandproc.communicate(code2)
print "output: %s\n error: %s\n" % (output, error)
我真的很想以某种方式让我可以code2
由同一个 sandproc 实例运行,但让它的输入/输出单独返回。如果我将所有代码连接在一起并立即运行它,它可以工作,但是解析给定输入的输出会有点痛苦。