Создать байт-код Python из списка опкодов и аргументов?

Есть ли простой способ создать байт-код Python из списка из 2-х кортежей с опкодами и их аргументами?

Например:

>>> bytecode_compile([
        ('LOAD_CONST', 2),
        ('STORE_FAST', 'a'),
        ('LOAD_FAST', 'a'),
        ('RETURN_VALUE',)])
'd\x01\x00}\x00\x00|\x00\x00S'

Ответ 1

Я не думаю, что существует ассемблер Python "сборка байт-кода", но, возможно, не так сложно его построить самостоятельно. В исходном коде python в Python-X.Y.Z/Include/opcode.h все байт-коды для кодов операций перечислены с аргументами, которые они принимают.

Ответ 2

Я подробно писал об этом здесь, поэтому я не буду повторять это, но дам некоторые краткие комментарии.

Это определенно выполнимо, но мне интересно, насколько это будет вообще полезно. Ссылка идет в том, как запустить и записать такие вещи.

Байт-код может быть изменен как с точки зрения кода операции, так и имен кода операции или семантики кодов операции между версиями. На самом деле, в Python 3.6 и выше байт-код становится кодовым словом.

Однако если вы решили пойти по этому пути, xdis недавно добавил функцию list2bytecode() чтобы сделать это.

Если вы предпочитаете работать в текстовом файле, так как написано большинство ассемблерного кода, я написал xasm для этого. Вот пример сборки в формате, который можно использовать:

# Python bytecode 3.6 (3379)

# Method Name:       five
# Filename:          /tmp/five.pl
# Argument count:    0
# Kw-only arguments: 0
# Number of locals:  0
# Stack size:        1
# Flags:             0x00000043 (NOFREE | NEWLOCALS | OPTIMIZED)
# First Line:        1
# Constants:
#    0: None
#    1: 5
  2:
            LOAD_CONST           (5)
            RETURN_VALUE


# Method Name:       <module>
# Filename:          /tmp/five.pl
# Argument count:    0
# Kw-only arguments: 0
# Number of locals:  0
# Stack size:        2
# Flags:             0x00000040 (NOFREE)
# First Line:        1
# Constants:
#    0: <code object five at 0x0000>
#    1: 'five'
#    2: None
# Names:
#    0: five
#    1: print
  1:
            LOAD_CONST           0 (<code object five at 0x0000>)
            LOAD_CONST           ('five')
            MAKE_FUNCTION        0
            STORE_NAME           (five)

  3:
            LOAD_NAME            (print)
            LOAD_NAME            (five)
            CALL_FUNCTION        0
            CALL_FUNCTION        1
            POP_TOP
            LOAD_CONST           (None)
            RETURN_VALUE