RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 797871
Accepted
Rennorb
Rennorb
Asked:2020-03-14 04:40:24 +0000 UTC2020-03-14 04:40:24 +0000 UTC 2020-03-14 04:40:24 +0000 UTC

.pycs 是如何组织的?

  • 772

你好!假设我们有以下代码:

x = 10

您需要获取与其对应的字节码。
让我们尝试编译它:

from dis import dis
dis('x=10')

我们得到:

  1           0 LOAD_CONST               0 (10)
              2 STORE_NAME               0 (x)
              4 LOAD_CONST               1 (None)
              6 RETURN_VALUE

或者,像这样(几乎相同):

from dis import Bytecode
bc = Bytecode('x=10')
list(bc.codeobj.co_code)
[100, 0, 90, 0, 100, 1, 83, 0]

在最后一个字节码中,有关常量的信息丢失了,尽管有LOAD_CONST(100)。

让我们尝试编译文件compileall:

>> python -m compileall ./
Listing './'...
Compiling './set.py'...

我们得到:

00 00 00 00 00 00 00 00 00 01 00 00 00 40 00 00
00 73 08 00 00 00 64 00 5A 00 64 01 53 00 29 02    
E9 0A 00 00 00 4E 29 01 DA 01 78 A9 00 72 03 00   
00 00 72 03 00 00 00 FA 08 2E 2F 73 65 74 2E 70
79 DA 08 3C 6D 6F 64 75 6C 65 3E 01 00 00 00 73    
00 00 00 00  

我在这段代码中找不到前一个。

这怎么解释?
一般来说,在哪里可以尊重它是如何安排的.pyc?

我想为 Python 编写自己的小型 VM。

python
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Sergey Gornostaev
    2020-03-14T13:35:18Z2020-03-14T13:35:18Z

    pyc 文件包括

    • 四字节幻数
    • 四字节时间戳
    • 四个字节存储源文件的大小
    • 序列化代码对象

    幻数是每个解释器版本唯一的两个字节和0d0a. 字节0d0a是回车和换行,可保护文件在文本模式下编辑时不被损坏。

    时间戳存储了源最后一次更改的时间,根据该时间生成pyc文件。

    有了尺寸,我确信一切都是显而易见的,不需要任何澄清。

    该文件的其余部分是在代码对象上运行marshal.dump的结果,而这又是编译源代码的结果。

    您可以使用此脚本“反汇编”pyc 文件:

    import dis, marshal, struct, sys, time, types
    from codecs import encode
    
    
    def show_file(fname):
        with open(fname, 'rb') as fh:
            magic = fh.read(4)
            moddate = fh.read(4)
            filesz = fh.read(4)
            modtime = time.asctime(time.localtime(struct.unpack('=L', moddate)[0]))
            filesz = struct.unpack('=L', filesz)
            print('magic {!s}'.format(encode(magic, 'hex').decode()))
            print('moddate {!s} ({!s})'.format(encode(moddate, 'hex').decode(), modtime))
            print('file size {:d}'.format(*filesz))
            code = marshal.load(fh)
            show_code(code)
    
    
    def show_code(code, indent=''):
        print('{!s}code'.format(indent))
        indent += '   '
        print('{!s}argcount {:d}'.format(indent, code.co_argcount))
        print('{!s}nlocals {:d}'.format(indent, code.co_nlocals))
        print('{!s}stacksize {:d}'.format(indent, code.co_stacksize))
        print('{!s}flags {:0>4x}'.format(indent, code.co_flags))
        show_hex('code', code.co_code, indent=indent)
        dis.disassemble(code)
        print('{!s}consts'.format(indent))
        for const in code.co_consts:
            if type(const) == types.CodeType:
                show_code(const, indent + '   ')
            else:
                print('   {!s}{!r}'.format(indent, const))
        print('{!s}names {!r}'.format(indent, code.co_names))
        print('{!s}varnames {!r}'.format(indent, code.co_varnames))
        print('{!s}freevars {!r}'.format(indent, code.co_freevars))
        print('{!s}cellvars {!r}'.format(indent, code.co_cellvars))
        print('{!s}filename {!r}'.format(indent, code.co_filename))
        print('{!s}name {!r}'.format(indent, code.co_name))
        print('{!s}firstlineno {:d}'.format(indent, code.co_firstlineno))
        show_hex('lnotab', code.co_lnotab, indent=indent)
    
    
    def show_hex(label, h, indent):
        h = encode(h, 'hex').decode()
        if len(h) < 60:
            print('{!s}{!s} {!s}'.format(indent, label, h))
        else:
            print ('{!s}{!s}'.format(indent, label))
            for i in range(0, len(h), 60):
                print('{!s}   {!s}'.format(indent, h[i:i+60]))
    
    
    show_file(sys.argv[1])
    

    在此脚本的 pyc 文件上运行它

    a, b = 1, 0
    if a or b:
        print('Hello', a)
    

    将给出以下输出

    magic 330d0d0a
    moddate 1094a85a (Wed Mar 14 11:16:32 2018)
    files sz 48
    code
       argcount 0
       nlocals 0
       stacksize 3
       flags 0040
       code
          64045c025a005a01650073106501721a6502640265008302010064035300
      1           0 LOAD_CONST               4 ((1, 0))
                  2 UNPACK_SEQUENCE          2
                  4 STORE_NAME               0 (a)
                  6 STORE_NAME               1 (b)
    
      2           8 LOAD_NAME                0 (a)
                 10 POP_JUMP_IF_TRUE        16
                 12 LOAD_NAME                1 (b)
                 14 POP_JUMP_IF_FALSE       26
    
      3     >>   16 LOAD_NAME                2 (print)
                 18 LOAD_CONST               2 ('Hello')
                 20 LOAD_NAME                0 (a)
                 22 CALL_FUNCTION            2
                 24 POP_TOP
            >>   26 LOAD_CONST               3 (None)
                 28 RETURN_VALUE
       consts
          1
          0
          'Hello'
          None
          (1, 0)
       names ('a', 'b', 'print')
       varnames ()
       freevars ()
       cellvars ()
       filename 'D:\\playground\\python\\test.py'
       name '<module>'
       firstlineno 1
       lnotab 08010801
    

    答案基于这篇文章。

    • 8

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5