Предупреждение PEP 3118 при использовании массива ctypes в качестве массива numpy
Я получаю следующее предупреждающее сообщение, когда пытаюсь использовать массив 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 ответа
Это ошибка в Python. В настоящее время ctypes создает недопустимые коды типов PEP 3118, которые замечает Numpy: http://bugs.python.org/issue10746 http://bugs.python.org/issue10744
Когда такое несоответствие присутствует, Numpy пропускает использование интерфейса буфера PEP 3118 и возвращается к старому (устаревшему) интерфейсу буфера. Это должно работать правильно.
Вы можете отключить предупреждение, используя Python warnings
модуль. Тем не менее, предупреждение может повлиять на производительность.
Вы также можете попробовать обойти эту проблему, обернув объект ctypes в buffer()
,
Есть более удобный способ сделать это, который полностью исключает предупреждение:
Вместо того, чтобы сначала создавать данные в виде массива 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)