Given a python .pyc file, is there a tool that let me view the bytecode?

后端 未结 2 1729
别那么骄傲
别那么骄傲 2020-12-28 10:17

A Python module is automatically compiled into a .pyc file by CPython interpreter. The .pyc file, which contains the bytecode, is in binary format (marshaled code?). Is ther

相关标签:
2条回答
  • 2020-12-28 10:47

    There's a visual python disassembler called PyChrisanthemum.

    To do it the command-line way you can use module dis (python 2.7.3, python 3.2.3), as OP already found out.

    0 讨论(0)
  • 2020-12-28 11:07

    Every *.pyc file is a binary file containing next things:

    • a four-byte magic number - it's simply bytes that change with each change to the marshalling code;
    • a four-byte modification timestamp - is the Unix modification timestamp of the source file that generated the .pyc, so that it can be recompiled if the source changes;
    • since version Python3.3+ next four bytes is field that encodes the size of the source file as a long;
    • a marshalled code object.

    Why not just use the CPython`s built-in features for this task?


    A file view_pyc_file.py

    import platform
    import time
    import sys
    import binascii
    import marshal
    import dis
    import struct
    
    
    def view_pyc_file(path):
        """Read and display a content of the Python`s bytecode in a pyc-file."""
    
        file = open(path, 'rb')
    
        magic = file.read(4)
        timestamp = file.read(4)
        size = None
    
        if sys.version_info.major == 3 and sys.version_info.minor >= 3:
            size = file.read(4)
            size = struct.unpack('I', size)[0]
    
        code = marshal.load(file)
    
        magic = binascii.hexlify(magic).decode('utf-8')
        timestamp = time.asctime(time.localtime(struct.unpack('I', b'D\xa5\xc2X')[0]))
    
        dis.disassemble(code)
    
        print('-' * 80)
        print(
            'Python version: {}\nMagic code: {}\nTimestamp: {}\nSize: {}'
            .format(platform.python_version(), magic, timestamp, size)
        )
    
        file.close()
    
    
    if __name__ == '__main__':
        view_pyc_file(sys.argv[1])
    

    Tested with next CPython`s versions:

    • 2.7.9
    • 3.4.2
    • 3.5.2

    Demonstration

    Content of a file main.py

    $ cat main.py
    print("Never give up")
    

    Create and to read pyc-file by the python2.7

    setivolkylany$~/Downloads/temp/temp$ python2.7 -m py_compile main.py 
    setivolkylany$~/Downloads/temp/temp$ python2.7 view_pyc_file.py ./main.pyc
      1           0 LOAD_CONST               0 ('Never give up')
                  3 PRINT_ITEM          
                  4 PRINT_NEWLINE       
                  5 LOAD_CONST               1 (None)
                  8 RETURN_VALUE        
    --------------------------------------------------------------------------------
    Python version: 2.7.9
    Magic code: 03f30d0a
    Timestamp: Fri Mar 10 15:08:20 2017
    Size: None
    

    Create and to read pyc-file by the python3.4

    setivolkylany$~/Downloads/temp/temp$ python3.4 -m py_compile main.py 
    setivolkylany$~/Downloads/temp/temp$ python3.4 view_pyc_file.py __pycache__/main.cpython-34.pyc 
      1           0 LOAD_NAME                0 (print)
                  3 LOAD_CONST               0 ('Never give up')
                  6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                  9 POP_TOP
                 10 LOAD_CONST               1 (None)
                 13 RETURN_VALUE
    --------------------------------------------------------------------------------
    Python version: 3.4.2
    Magic code: ee0c0d0a
    Timestamp: Fri Mar 10 15:08:20 2017
    Size: 23
    

    Create and to read pyc-file by the python3.5

    setivolkylany$~/Downloads/temp/temp$ python3.5 -m py_compile main.py 
    setivolkylany$~/Downloads/temp/temp$ python3.5 view_pyc_file.py __pycache__/main.cpython-35.pyc 
      1           0 LOAD_NAME                0 (print)
                  3 LOAD_CONST               0 ('Never give up')
                  6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                  9 POP_TOP
                 10 LOAD_CONST               1 (None)
                 13 RETURN_VALUE
    --------------------------------------------------------------------------------
    Python version: 3.5.2
    Magic code: 160d0d0a
    Timestamp: Fri Mar 10 15:08:20 2017
    Size: 23
    

    Based on:

    • How can I understand a .pyc file content
    • https://gist.github.com/anonymous/35c08092a6eb70cdd723
    • https://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html
    0 讨论(0)
提交回复
热议问题