In [3]: def cond():
...: x = 1
...: y = 2
...: return x + y
...:
In [4]: cond.__code__
Out[4]: <code object cond at 0x7f037ebeb540, file "<ipython-input-3-27b19c0276da>", line 1>
In [5]: type(cond)
Out[5]: function
In [6]: type(cond.__code__)
Out[6]: code
In [7]: cond.__code__.co_code
Out[7]: b'd\x01}\x00d\x02}\x01|\x00|\x01\x17\x00S\x00'
In [8]: type(cond.__code__.co_code)
Out[8]: bytes
def run_python_module(modulename, args):
....
# Finally, hand the file off to run_python_file for execution.
run_python_file(pathname, args, package=packagename)
def run_python_file(filename, args, package=None):
# Create a module to serve as __main__
....
# Set sys.argv and the first path element properly.
....
try:
# Open the source file.
try:
source = source_file.read()
finally:
source_file.close()
....
# We have the source. `compile` still needs the last line to be clean,
# so make sure it is, then compile a code object from it.
if not source or source[-1] != '\n':
source += '\n'
code = compile(source, filename, "exec")
# Execute the source file.
exec_code_object(code, main_mod.__dict__)
finally:
# Restore the old __main__
....
# Restore the old argv and path
....
def run_code(self, code, f_globals=None, f_locals=None):
frame = self.make_frame(code, f_globals=f_globals, f_locals=f_locals)
val = self.run_frame(frame)
# Check some invariants
if self.frames: # pragma: no cover
raise VirtualMachineError("Frames left over!")
if self.frame and self.frame.stack: # pragma: no cover
raise VirtualMachineError("Data left on stack! %r" % self.frame.stack)
return val
def run_frame(self, frame):
"""Run a frame until it returns (somehow).
Exceptions are raised, the return value is returned.
"""
self.push_frame(frame)
while True:
byteName, arguments, opoffset = self.parse_byte_and_args()
if log.isEnabledFor(logging.INFO):
self.log(byteName, arguments, opoffset)
# When unwinding the block stack, we need to keep track of why we
# are doing it.
why = self.dispatch(byteName, arguments)
if why == 'exception':
# TODO: ceval calls PyTraceBack_Here, not sure what that does.
pass
if why == 'reraise':
why = 'exception'
if why != 'yield':
while why and frame.block_stack:
# Deal with any block management we need to do.
why = self.manage_block_stack(why)
if why:
break
# TODO: handle generator exception state
self.pop_frame()
if why == 'exception':
six.reraise(*self.last_exception)
return self.return_value
def call_function(self, arg, args, kwargs):
lenKw, lenPos = divmod(arg, 256)
namedargs = {}
for i in range(lenKw):
key, val = self.popn(2)
namedargs[key] = val
namedargs.update(kwargs)
posargs = self.popn(lenPos)
posargs.extend(args)
func = self.pop()
frame = self.frame
if hasattr(func, 'im_func'):
# Methods get self as an implicit first parameter.
if func.im_self:
posargs.insert(0, func.im_self)
# The first parameter must be the correct type.
if not isinstance(posargs[0], func.im_class):
raise TypeError(
'unbound method %s() must be called with %s instance '
'as first argument (got %s instance instead)' % (
func.im_func.func_name,
func.im_class.__name__,
type(posargs[0]).__name__,
)
)
func = func.im_func
retval = func(*posargs, **namedargs)
self.push(retval)
def __call__(self, *args, **kwargs):
if PY2 and self.func_name in ["<setcomp>", "<dictcomp>", "<genexpr>"]:
# D'oh! http://bugs.python.org/issue19611 Py2 doesn't know how to
# inspect set comprehensions, dict comprehensions, or generator
# expressions properly. They are always functions of one argument,
# so just do the right thing.
assert len(args) == 1 and not kwargs, "Surprising comprehension!"
callargs = {".0": args[0]}
else:
callargs = inspect.getcallargs(self._func, *args, **kwargs)
frame = self._vm.make_frame(
self.func_code, callargs, self.func_globals, {}
)
CO_GENERATOR = 32 # flag for "this code uses yield"
if self.func_code.co_flags & CO_GENERATOR:
gen = Generator(frame, self._vm)
frame.generator = gen
retval = gen
else:
retval = self._vm.run_frame(frame)
return retval
def __call__(self, *args, **kwargs):
if PY2 and self.func_name in ["<setcomp>", "<dictcomp>", "<genexpr>"]:
# D'oh! http://bugs.python.org/issue19611 Py2 doesn't know how to
# inspect set comprehensions, dict comprehensions, or generator
# expressions properly. They are always functions of one argument,
# so just do the right thing.
assert len(args) == 1 and not kwargs, "Surprising comprehension!"
callargs = {".0": args[0]}
else:
callargs = inspect.getcallargs(self._func, *args, **kwargs)
frame = self._vm.make_frame(
self.func_code, callargs, self.func_globals, {}
)
CO_GENERATOR = 32 # flag for "this code uses yield"
if self.func_code.co_flags & CO_GENERATOR:
gen = Generator(frame, self._vm)
frame.generator = gen
retval = gen
else:
retval = self._vm.run_frame(frame)
return retval