Рубрики
Без рубрики

Как создать сырье Bytecode в Python

Вступление Ну, сначала я начал делать это на github.io, но тогда группа виртуа … Теги с байтекодом, Python, учебником, программированием.

Вступление

Ну, сначала я начал делать это на github.io Но тогда группа виртуальных гангстеров избила меня и заставила меня понять, что нет смысла использовать этот фантастический веб-сайт. Ну, там есть, я использую это, так как гласит титул, это уравнительный участок Raw Python Bytecode, я надеюсь, что вам понравится (потому что есть вторая часть …)

Предварительно требования

  • Основные знания о Python
  • Знать, что объект байта является
  • Знать концепцию куча

Что такое питон?

Python – это многопараметрический интерпретантный язык программирования, он поддерживает полиморфизм, объектно-ориентированное программирование (OOP/OOP) и императивное программирование.

Как это работает?

Python, как уже названо, является интерпретированным языком, это означает, что он проходит через интерпретатор, который соединяет то, что будет делать компьютер, с тем, что вы пишете. Python не генерирует машинный код как программа C или C ++ будет генерировать, а скорее работает более или менее похожа на Java, она имеет виртуальную машину, которая интерпретирует Bytecode. Этот интерпретатор по умолчанию является cpython, который отвечает за выполнение байткода на вашем компьютере. Здесь мы не собираемся использовать компиляторы, а скорее мы собираемся обрабатывать языковые реализации, в основном переводчикам, которые интерпретируют (простите резервирование) письменный код после перевода его в Bytecode. Это широкое разнообразие, например, Ironpython (Реализация C #), Jython (Реализация чистого Java), Microphton (версия C оптимизирована для запуска на микроконтроллерах). Вот схема того, как работает Python, а шаги, которые переводчик принимает, чтобы запустить код, который вы написали.

Как создать пригодной для использования Bytecode

Что ж, у нас есть две вещи, сначала зачеркнутые байткод, то есть байты в шестнадцатеричном, представляющем опкоды и параметры, а во-вторых, у нас есть CodeType , тип данных в Python, который помогает нам создавать Bytecode, который Подходит и полезно . Также для сборки, вы должны знать, как разобрать, мы собираемся использовать модуль дес Этот модуль используется для разборки функций, файлов и кода.

import dis

def sum (x, y):
    return x + y
dis.dis (sum)

Вывод этого фрагмента кода выглядит следующим образом

1. 4   0 LOAD_FAST    0 (x)
2.     2 LOAD_FAST    1 (y)
3.     4 BINARY_ADD
4.     6 RETURN_VALUE
>>>

Как мы видим, все это есть Bytecode, теперь объяснение.

Как вы, возможно, заметили, я перечислил линии на выходе, чтобы облегчить это объяснение. Каждая инструкция в Python имеет определенный операционный код (код работы), в этом случае мы используем 3, Load_fast binary_add return_value Мы объясним, что делает каждый.

  • Load_Fast: загружает переменную в верхнюю часть стека (верхняя часть стека).
  • Binary_add: добавьте два значения в верхней части стека и верните их в верхнюю часть стека.
  • Return_value: Возвращает значение, которое находится в TOS.

Ну, теперь, когда мы объяснили Опкоды, мы можем получить представление о том, как наш код работает внутри, но есть все еще сомнения, раздражает, но необходимые сомнения, как это, «что 4 на левой стороне, 4 Это в начале первой линии? »,« Каковы числа слева от оправа? «Почему 0 появляется справа от Load_Fast?, А 1?», «Мы не хотели бы загружать X и y Чтобы добавить их вместо 0 и 1? “.

Ну, я отвечу в порядок.

  • 4 – это линия, где начинается разобранный байт-код.
  • Эти цифры представляют собой Смещение байтов.
  • 0 и 1 соответствуют индексу, поскольку переменные кода хранятся в списке (массив), 0 и 1 представляют индекс, однако, модуль не позволяет нам, какая переменная справа от этого номера ( Следовательно, 0 (х) и 1 (Y) ). *

Как мы повторно создайте нашу функцию, чтобы сделать его Bytecode?

Ну, первое, что мы делаем, это импортировать CodeType и Функциональныйype. (Чтобы пройти его на функцию) из модуля [Типов] ( https://docs.cython.org/3/library/types.html#module-types )

import dis
from types import CodeType, FunctionType

def sum (x, y):
    return x + y

После этого мы собираемся создать наш объектный код Python

import dis
from types import CodeType, FunctionType

def sum (x, y):
    return x + y

# This will be explained later, these are flags
CO_OPTIMIZED = 0x0001
CO_NEWLOCALS = 0x0002
CO_NOFREE = 0x0002

my_code = CodeType (
    2, #argcount
    0, #kwonlyargcount
    2, #nlocals
    2, #stacksize
    (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE), #flags
    bytes ([124, 0, 124, 1, 23, 0, 83, 0]), #codestring
    (0,), #constants
    (), # names of constants or global (names)
    ('x', 'y',), #variable names (varnames)
    'blog_no_name', #filename
    'crafted_sum', #name (code name / function)
     9, #Firstlineno (First line where this code appears)
     b'', #lnotab
     (), #freevars
     (), # freecellvars
     )

_sum = FunctionType (my_code, {})
result = _sum (213,3)
print (result)

# Expected output
# 216

Так так … Появляются много новых вещей, мы объясним эти аргументы прямо сейчас.

CodeType: argcount, kwonlyargcount, nlocals, stacksize, флаги, кодировщик, константы, имена, varnames, filename, имя, firstlineno, lnotab, freevars, FreeCellvars

argcount. Количество аргументов
kwonlyargcount. Количество аргументов ключевых слов
nlocals. Количество локальных переменных ( В этом случае 2, X и Y)
укладки Максимальный размер в байтах, что у стека будет (в этом случае 2 Потому что X Y требует двух пробелов в кадре стека)
флаги Флаги – это то, что определяют некоторые условия байткода, вы можете руководствоваться этой ссылкой. Мы собираемся углубиться на флаги в более продвинутом уроке.
косо Это список (массив) байтов, содержащих под вопросом последовательности, в 124 это означает load_fast, 23 binary_add и 83 return_value
константы Кортеж со значением констант (таких как целые числа, ложные, правдивые, встроенные функции …)
имен Кортеж, содержащий имя констант соответственно
варки Локальное имя переменной
имя файла Эта строка представляет имя файла, когда это значение не используется, это может быть любая строка
имя Имя объекта кода или функции
Firstlineno. Представляет первую строку, в которой код выполнен, актуален, если мы импортируем файл, в противном случае это может быть любое целое число
lnotab. Это отображение между смещениями объекта Bytecode и смещением линий, если вы не заинтересованы в положении информации на линии, вы можете использовать B ”
Freevars Я объясню эти переменные в продвинутом уроке, он используется в закрытиях
CellVars Эти переменные определяются в закрытии

Последние две вещи, чтобы заметить, прежде чем перейти к FUNGHTYPE первый в том, что 0s, которые следуют за оправами *, например, [124, 0, …] * – это аргумент, а во-вторых, каждый бассейн может варьироваться от версии к версии, чтобы узнать или ориентировать себя о кодировке, вы можете использовать следующие фрагмент

def sum (x, y):
    return x + y
sum.__ code __.co_code

# Expected output in Python 3.7.9 (The version I use)
# b '|\x00|\x01\x17\x00S\x00'
# The bytes are interpreted as characters, probably to make it more readable. (If we put chr (124) it will print the character |)

«Крафтирование» функция

Мы собираемся использовать FunctionType сейчас. FunctionType: код, глобалы, имя, аргументы, закрытие

код Объектный код (OSEA, CodeType)
глобали Словарь, содержащий глобал следующим образом: {“name”: valuename} `Таким образом, имя становится идентификатором, а затем доступно, как если бы это была переменная
Имя (необязательно) Переопределить значение объекта кода)
argdefs (необязательно) Кортеж, который определяет значение аргументов по умолчанию
закрытие (необязательно) Кортеж, который снабжает связи для FreeVars

Ну, как только это понятно, теперь нам придется добавить функции только с нашим объектом ( my_code ) и вызовите его.

import dis
from types import CodeType, FunctionType

def sum (x, y):
    return x + y

После этого мы собираемся создать наш объектный код

import dis
from types import CodeType, FunctionType

def sum (x, y):
    return x + y

# This I will explain later, they are flags
CO_OPTIMIZED = 0x0001
CO_NEWLOCALS = 0x0002
CO_NOFREE = 0x0002

my_code = CodeType (
    2, #argcount
    0, #kwonlyargcount
    2, #nlocals
    2, #stacksize
    (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE), #flags
    bytes ([124, 0, 124, 1, 23, 0, 83, 0]), #codestring
    (0,), #constants
    (), # names of constants or global (names)
    ('x', 'y',), #variable names (varnames)
    'blog_no_name', #filename
    'crafted_sum', #name (code / function name)
    9, #Firstlineno (First line where this code appears)
    b '', #lnotab
    (), #freevars
    (), # freecellvars
    )

_sum = FunctionType (my_code, {})
result = _sum (213,3)
print (result)

# Expected output
# 216

Это все сейчас, позже я загрузим еще один учебник, объясняющий замыкание

Источники

Оригинал: “https://dev.to/torswq/how-to-create-raw-bytecode-i-299f”