Pythonic способ скопировать список в sip.voidptr из QSharedMemory - PullRequest
0 голосов
/ 04 июля 2018

Я использую PyQT5 и класс QSharedMemory. Я создаю общую память, которая может содержать 6 1-байтовых элементов. Чтобы скопировать эти элементы в массиве совместно используемой памяти, я перебираю элементы из списка python, как показано ниже:

f = shared_mem.data()
k = f.asarray()
memtocopy = [0,1,2,3,4,5]
for i in range(0,len(memtocopy)):
    k[i]  = memtocopy[i]
shared_mem.unlock()

Что выглядит очень не пифонично и похоже на шаблонный код. Мне интересно, есть ли более подходящий способ достижения того же результата?

При использовании

k[:] = memtocopy

или

k[:] = np.asarray(memtocopy,np.uint8)

Ошибка с сообщением об ошибке:

TypeError: can only assign another array of unsigned char to the slice

Весь тестовый код для воспроизведения выглядит следующим образом:

from PyQt5 import QtCore 

# Create shared memory and attach it
shared_mem = QtCore.QSharedMemory()
shared_mem.setNativeKey("test")
shared_mem.create(4*6)
shared_mem.attach()


# Fill in 
shared_mem.lock()
f = shared_mem.data()
k = f.asarray()

memtocopy = [0,1,2,3,4,5]

# Loop in question
for i in range(0,len(memtocopy)):
    k[i]  = memtocopy[i]

shared_mem.unlock()



# Read out
shared_mem.lock()
f1 = shared_mem.data()
k1 = f1.asarray()
shared_mem.unlock()

# Test results
if k1[0] == memtocopy[0]:
    print("success!")
else:
    print("fail!")

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Вот более простой подход с использованием struct и memoryview , который считывает и записывает данные с помощью пары строк :

import struct
from PyQt5 import QtCore

shared_mem = QtCore.QSharedMemory()
shared_mem.setNativeKey("test")
shared_mem.create(4*6)
shared_mem.attach()

memtocopy = [0,1,2,3,4,5]

try:

    # Fill in 
    shared_mem.lock()
    shared_mem.data()[:] = memoryview(struct.pack('=6i', *memtocopy))
    shared_mem.unlock()

    # Read out
    shared_mem.lock()
    # python3
    k = memoryview(shared_mem.data()).cast('i')
    # python2
    # k = struct.unpack('=6i', memoryview(shared_mem.data()))
    shared_mem.unlock()

    if k[3] == memtocopy[3]:
        print("success!")
    else:
        print("fail!")

finally:

    shared_mem.detach()
0 голосов
/ 04 июля 2018

После небольшого возни, мне удалось создать одну комбинацию, которая работала для меня:

a = array.array('i', range(6))
f[:] = buffer(a)
b = array.array('i')
b.fromstring(buffer(f))

Это полагается на буферный протокол для чтения в обоих направлениях. Вероятно, вы можете использовать массив напрямую с вашим k, а fromstring был переименован в frombytes в более поздних версиях.

В Python 3.4 это сработало:

a = array.array('i', range(6))
f[:] = memoryview(a).cast('B')
b = array.array('i')
b.frombytes(memoryview(f))

memoryview заменил buffer, но знал, что элементы имеют размер 4 байта, поэтому потребовалось дополнительное приведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...