可以从脚本执行Python字节码吗?

时间:2015-04-27 13:42:05

标签: python-3.x cpython

假设我有一个正在运行的CPython会话,

有没有办法直接从bytes文件运行数据(pyc)? (没有必要的磁盘数据,无需编写临时的pyc文件)

显示简单用例的示例脚本:

if foo:
    data = read_data_from_somewhere()
else:
    data = open("bar.pyc", 'rb').read()

assert(type(data) is bytes)

code = bytes_to_code(data)

# call a method from the loaded code
code.call_function()

确切使用并不重要,但动态生成代码并通过网络复制执行是一个用例(为了考虑这个问题)。

以下是一些示例用例,这让我很想知道如何做到这一点:

  • 检查Python脚本是否存在恶意代码。
    如果单个命令可以访问隐藏在二进制数据中的大量代码,那么该命令会是什么样的?
  • 动态生成代码并将其缓存以供重复使用(不一定在磁盘上,例如可以使用数据库)。
  • 能够将预编译的字节代码发送到进程,控制嵌入Python的应用程序,例如

2 个答案:

答案 0 :(得分:8)

  

有没有办法直接从pyc文件运行数据?

可以使用marshal

保存已编译的代码对象
import marshal
bytes = marshal.dumps(eggs)

可以将字节转换回代码对象

eggs = marshal.loads(bytes)
exec(eggs)

pyc文件是带有标题

的封送代码对象

对于Python3,标题为12个字节,需要跳过,其余数据可以通过marshal.loads读取。

请参阅Ned Batchelder's blog post

  

在简单级别,.pyc文件是一个二进制文件,只包含三件事:

     
      
  • 一个四字节幻数,
  •   
  • 四字节修改时间戳,
  •   
  • 编组代码对象。
  •   

注意,该链接引用Python2,但它在Python3中几乎相同,pyc标题大小只有12而不是8个字节。

答案 1 :(得分:1)

假设已编译的.pyc的平台是正确的,您可以导入它。因此,在python路径中使用文件bar.pyc,即使bar.py不存在,以下内容仍然有效:

import bar
bar.call_function()