Предупреждение PEP 3118 при использовании массива ctypes в качестве массива numpy - PullRequest
10 голосов
/ 11 февраля 2011

При попытке использовать массив ctypes в качестве массива numpy я получаю следующее предупреждение:

Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes, numpy
>>> TenByteBuffer = ctypes.c_ubyte * 10
>>> a = TenByteBuffer()
>>> b = numpy.ctypeslib.as_array(a)
C:\Python27\lib\site-packages\numpy\ctypeslib.py:402: RuntimeWarning: Item size
computed from the PEP 3118 buffer format string does not match the actual item s
ize.
  return array(obj, copy=False)
>>> b
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=uint8)

Код, похоже, работает. Это плохая идея игнорировать это предупреждение?

Справочная информация: Я звоню в C DLL, которая производит данные в режиме реального времени. Мне нужно передать DLL ряд буферов для хранения данных. В ожидании заполнения следующего буфера я бы хотел обработать самый последний буфер с помощью numpy и сохранить результат. Я генерирую буферы с кодом, как описано выше, и кажется, что все работает, но я не хочу скрывать важную проблему под ковриком.

Ответы [ 2 ]

11 голосов
/ 11 февраля 2011

Это ошибка в Python.В настоящее время ctypes создает недопустимые коды типов PEP 3118, которые Numpy замечает: http://bugs.python.org/issue10746 http://bugs.python.org/issue10744

При наличии такой несогласованности Numpy пропускает, используя интерфейс буфера PEP 3118, и возвращается к старому(устаревший) интерфейс буфера.Это должно работать правильно.

Вы можете отключить предупреждение, используя модуль Python warnings.Тем не менее, предупреждение может повлиять на производительность.

Вы также можете попытаться обойти проблему, поместив объект ctypes в buffer().

3 голосов
/ 11 февраля 2011

Существует более удобный способ сделать это, который полностью исключает предупреждение:

Вместо того, чтобы сначала создавать данные в виде массива ctypes, а затем преобразовывать их в массив NumPy, просто создайте их как NumPy.сразу массив, а затем используйте numpy.ctypeslib.ndpointer в качестве спецификатора типа в вашем прототипе ctypes.В качестве примера, скажем, у вас есть функция C с именем f, которая принимает char* и size_t в качестве аргументов:

void f(char* buf, size_t len);

Ваш прототип ctypes будет

from numpy.ctypeslib import ndpointer
some_dll = ctypes.CDLL(...)
some_dll.f.argtypes = [ndpointer(numpy.uint8, flags="C_CONTIGUOUS"),
                       ctypes.c_size_t]
some_dll.f.restype = None

и вы можете вызвать эту функцию как

a = numpy.zeros(10, numpy.uint8)
f(a, a.size)
...