Расширение Python – создание и проверка больших целых чисел эффективно

У меня есть собственная библиотека, для которой естественный интерфейс будет включать в себя передачу потенциально больших чисел. Я ожидаю, что половина будет <32 бит; другой квартал <64 бит; следующий восьмой <128 бит – и т. д., без ограничения фиксированной длины.

PyLong_FromUnsignedLongLong () и PyLong_AsUnsignedLongLong () были бы подходящими, если бы я мог ограничить значения, чтобы они поместились в один регистр.

PyLong_FromString () преодолевает это, но при нежелательном расходе требуется промежуточное представление. _PyLong_FromByteArray () и _PyLong_AsByteArray () уменьшают эту стоимость (делая это промежуточное представление простым), но ведущее подчеркивание заставляет меня задаться вопросом, может ли это привести к проблемам с переносимостью.

В longintrepr.h я нашел struct _longobject … который намекает, что это может быть способ напрямую взаимодействовать с внутренним представлением … хотя отсутствие подробной документации об этой структуре остается препятствием.

Какой подход приведет к оптимальной пропускной способности между Python и библиотекой? Есть ли документация, которую я забыл?

2 Solutions collect form web for “Расширение Python – создание и проверка больших целых чисел эффективно”

Префикс подчеркивания в значительной степени означает то же самое в C API, что и в обычном Python: «эта функция представляет собой деталь реализации, подлежащую изменению, поэтому следите за собой, если вы ее используете». Вам не запрещено использовать такие функции, и если это единственный способ достичь определенной цели (например, значительная прибыль от повышения эффективности в вашем случае), тогда это нормально использовать API, если вы знаете об опасности.

Если API-интерфейс _PyLong_FromByteArray был действительно закрытым, он был бы static функцией и не был бы полностью документирован и экспортирован в longobject.h . Фактически, Тим Петерс (известный разработчик Python) явно благословляет его использование :

[Дэн Кристенсен]

Мой студент и я пишем расширение C, которое производит большое целое число в двоичном формате, которое мы хотели бы преобразовать в python долго. Количество бит может быть намного больше, чем 32 или даже 64. Мой ученик нашел функцию _PyLong_FromByteArray в longobject.h, что именно то, что нам нужно, но ведущее подчеркивание заставляет меня насторожиться. Безопасно ли использовать эту функцию?

Python использует его внутри, поэтому лучше быть 😉

Будет ли он продолжать существовать в будущих версиях python?

Никаких гарантий, и поэтому он имеет лидирующий знак: это официально не поддерживаемая, задокументированная часть рекламируемого API Python / C. Так получилось, что я добавил эту функцию, потому что Python нуждался в некоторой форме своей функциональности внутри разных C-модулей. Сделать его официальной частью API Python / C было бы намного больше работы (на что у меня не было времени), и создал вечную новую нагрузку на обслуживание (которой я не увлекаюсь независимо ;-)).

На практике мало кто затрагивает эту часть реализации Python, поэтому я не ожидаю / не уйду или даже не изменится на долгие годы. Самая большая неуверенность, о которой я могу думать, заключается в том, что кто-то может начать крестовый поход, чтобы сделать какой-то другой байтовый массив <-> длинный интерфейс «официальный», основанный на другом способе представления отрицательных целых чисел. Но даже тогда я ожидаю, что текущие неофициальные функции останутся, поскольку представление 256 -множественного дополнения остается необходимым для формата «q» struct модуля, а для протокола протокола pickle = 2 длинного формата сериализации.

Или есть какой-то другой метод, который мы должны использовать?

Нет. Вот почему эти функции были изобретены для начала 😉

Вот документация (из Python 3.2.1):

 /* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in base 256, and return a Python long with the same numeric value. If n is 0, the integer is 0. Else: If little_endian is 1/true, bytes[n-1] is the MSB and bytes[0] the LSB; else (little_endian is 0/false) bytes[0] is the MSB and bytes[n-1] the LSB. If is_signed is 0/false, view the bytes as a non-negative integer. If is_signed is 1/true, view the bytes as a 2's-complement integer, non-negative if bit 0x80 of the MSB is clear, negative if set. Error returns: + Return NULL with the appropriate exception set if there's not enough memory to create the Python long. */ PyAPI_FUNC(PyObject *) _PyLong_FromByteArray( const unsigned char* bytes, size_t n, int little_endian, int is_signed); 

Основная причина, по которой это «подчёркнутый» префиксный API, заключается в том, что он зависит от реализации Python long как массива слов в базе данных «сила-два». Это вряд ли изменится, но поскольку вы используете API поверх этого, вы можете позже изолировать своих абонентов от изменений в Python API.

Похоже, вам нужен PyNumber_Long . Некоторые док-хиты здесь .

  • .so не импортирует в python: динамический модуль не определяет функцию init
  • Большие данные POST повреждены при использовании Django / PyISAPIe / IIS
  • Создание объекта с использованием API Python C
  • Создание массива numpy объектов пользовательского класса с C API
  • Что такое PyClass_New эквивалент в Python 3?
  • Python (и API Python C): __new__ против __init__
  • Импорт и использование стандартного модуля Python из внутреннего расширения Python C
  • Можно ли перевести dtype scipy CSR-матрицы в NPY_FLOAT?
  • NumPy C-API: преобразовать тип объекта в тип номера
  • В Python, почему модуль, реализованный на C быстрее, чем чистый модуль Python, и как его написать?
  • вызов C ++ с использованием функции Eigen Library в python
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.