I'm currently experimenting with QSharedMemory
and QProcess
in PyQt. So I wrote a small application to launch a process, which creates a shared memory segment and writes data to it. The application reads the data back when the process writes on the output.
Unfortunately, I get this error when the application attempts to attach to the shared memory segment: QSharedMemory::handle: doesn't exist
. It seems like the parent process cannot access the shaderd memory segment allocated by a child process unless the memory segment is allocated by the parent itself.
Output trace:
process state: Starting
process state: Running
process started
process output: Done writing to shared memory
Error accessing shared memory from parent process QSharedMemory::handle: doesn't exist
Error accessing data
process state: Not running
process finished
My application code:
from PyQt4 import QtGui, QtCore
import sys
import pickle
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget,self).__init__()
# create process
self.p = QtCore.QProcess(self)
# Connect to process output
self.p.readyReadStandardOutput.connect( self.on_process_output )
self.p.readyReadStandardError.connect( self.on_process_error_output )
self.p.stateChanged.connect(self.on_process_state_change)
self.p.finished.connect(self.on_process_finished)
self.p.started.connect(self.on_process_started)
self.p.error.connect( self.on_process_error )
self.key = 'share_mem_key'
self.shmem = QtCore.QSharedMemory( self.key )
self.p.start( 'python.exe shmem_process_test.py "%s"' % self.key )
def on_process_output(self):
s_out = bytes.decode( bytes( self.sender().readAllStandardOutput() ) )
print 'process output: %s' % (s_out)
if not self.shmem.isAttached() and not self.shmem.attach():
print 'Error accessing shared memory from parent process: %s ' % self.shmem.errorString()
self.shmem.lock()
try:
data = self.shmem.data()
if data:
print pickle.loads(data.asstring())
finally:
print 'Error accessing data'
self.shmem.unlock()
def on_process_error_output(self):
s_out = bytes.decode( bytes( self.sender().readAllStandardError() ) )
print 'process output: %s' % (s_out)
def on_process_state_change(self,new_state):
states = ["Not running", "Starting", "Running"]
print 'process state: %s' % (states[new_state])
def on_process_finished(self):
print 'process finished'
def on_process_started(self):
print 'process started'
def on_process_error(self):
print 'process error'
# application loop
app = QtGui.QApplication(sys.argv)
widget = Widget()
widget.show()
app.exec_()
My process code:
from PyQt4 import QtCore
import ctypes
import ctypes.util
import pickle
import sys
CLIB = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
def main(argv):
key = argv[1]
# write to shared memory
data = range(开发者_如何转开发50)
data_bytes = pickle.dumps( data, pickle.HIGHEST_PROTOCOL)
data_len = len(data_bytes)
shmem = QtCore.QSharedMemory(key)
if not shmem.create(data_len):
sys.stderr.write( 'ERROR: shared memory creation' )
sys.stderr.flush()
return
if not shmem.isAttached() and not shmem.attach():
sys.stderr.write( 'ERROR: shared memory access' )
sys.stderr.flush()
return
shmem.lock()
try:
CLIB.memcpy(int(shmem.data()), data_bytes, data_len)
finally:
shmem.unlock()
sys.stdout.write( "Done writing to shared memory" )
sys.stdout.flush()
if __name__ == '__main__':
main(sys.argv)
From the QSharedMemory docs (emphasis mine):
Warning: QSharedMemory changes the key in a Qt-specific way. It is therefore currently not possible to use the shared memory of non-Qt applications with QSharedMemory.
Not sure you can do what you want (portably anyway).
精彩评论