Python bytecode utilities

2024.7.31 · active · verified Sun Apr 12

Pycnite is a collection of utilities for working with compiled Python bytecode. This library provides pure Python, versioned parsers for the .pyc format, enabling tools that work with bytecode to support different host and target Python versions. It currently supports target Python versions 3.8 through 3.12.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to programmatically compile a Python source file into a .pyc file using the standard `py_compile` module, and then use `pycnite` to load and inspect the compiled bytecode. This allows for programmatic analysis of Python's low-level execution instructions and metadata contained within .pyc files. Ensure the `dummy_pyc_path` matches the actual filename convention for your Python version (e.g., `cpython-310.pyc` for Python 3.10).

import os
import py_compile
import tempfile

# Create a dummy Python file
dummy_py_content = '''
def greet(name):
    message = f"Hello, {name}!"
    return message

result = greet("World")
'''

# Use tempfile to create and manage temporary files
with tempfile.TemporaryDirectory() as tmpdir:
    dummy_py_path = os.path.join(tmpdir, 'dummy_module.py')
    dummy_pyc_path = os.path.join(tmpdir, '__pycache__', 'dummy_module.cpython-310.pyc') # Adjust for your Python version

    with open(dummy_py_path, 'w') as f:
        f.write(dummy_py_content)

    # Compile the .py file to .pyc
    # py_compile automatically creates __pycache__ and the .pyc file
    py_compile.compile(dummy_py_path, cfile=dummy_pyc_path, doraise=True)

    print(f"Generated .pyc file at: {dummy_pyc_path}")
    
    try:
        from pycnite import pyc

        # Load the .pyc file using pycnite
        # You may need to specify the Python version if pycnite can't infer it
        # For example, pyc.load_pyc(dummy_pyc_path, python_version=(3, 10))
        pyc_file = pyc.load_pyc(dummy_pyc_path)

        print(f"\nLoaded .pyc file successfully. Python version: {pyc_file.version}")
        print(f"Magic number: {hex(pyc_file.magic)}")

        # Accessing the code object (example for the module's code object)
        code_obj = pyc_file.code
        print(f"\nCode object name: {code_obj.co_name}")
        print(f"Number of arguments: {code_obj.co_argcount}")
        print(f"Constants: {code_obj.co_consts}")
        print(f"Names used: {code_obj.co_names}")
        # print(f"Disassembled bytecode:\n{code_obj.dis()}") # Requires 'dis' module and pycnite's dis method

    except ImportError:
        print("\nPycnite not installed. Skipping pycnite specific checks.")
    except Exception as e:
        print(f"\nError loading .pyc with pycnite: {e}")

view raw JSON →