2008-11-13 22 views
8

Estoy desarrollando una aplicación con un equipo en .Net (C++) y proporciono una interfaz COM para interactuar con python y otros lenguajes.¿Cuál es la mejor manera de transferir datos de python a otra aplicación en Windows?

Lo que hemos encontrado es que presionar datos a través de COM resulta ser bastante lento.

He considerado varias alternativas:

  • volcar los datos a un archivo y enviar la ruta del archivo a través com
  • memoria compartida a través de mmap?
  • ¿Transmitir datos a través de un socket directamente?

Según su experiencia, ¿cuál es la mejor forma de pasar datos?

+0

¿Son enormes cantidades de datos? ¿Lo estás serializando? ¿Cuál es la naturaleza de los datos? –

+0

En la mayoría de los casos, básicamente datos de lat/lon point. Y en este momento se ha pasado directamente a través de COM, algo así como. AddPoint (lat, lon). – monkut

Respuesta

9

Manteniéndonos dentro de los mecanismos de comunicación entre procesos de Windows, tuvimos una experiencia positiva al usar las ventanas llamadas tuberías. Utilizando Windows superpuesto IO y el módulo win32pipe de pywin32.

Puedes aprender mucho sobre win32 y python en el libro Python Programming On Win32.

La parte de envío simplemente escribe en r'\\.\pipe\mypipe'.

Un objeto listener (ovpipe) contiene un identificador de evento, y la espera de un mensaje con otros posibles eventos implica llamar al win32event.WaitForMultipleObjects.

rc = win32event.WaitForMultipleObjects(
    eventlist, # Objects to wait for. 
    0,   # Wait for one object 
    timeout)  # timeout in milli-seconds. 

aquí es parte de la pitón se superponen clase de escucha:

import win32event 
import pywintypes 
import win32file 
import win32pipe 

class ovpipe: 
"Overlapped I/O named pipe class" 
def __init__(self): 
    self.over=pywintypes.OVERLAPPED() 
    evt=win32event.CreateEvent(None,1,0,None) 
    self.over.hEvent=evt 
    self.pname='mypipe' 
    self.hpipe = win32pipe.CreateNamedPipe(
     r'\\.\pipe\mypipe',    # pipe name 
     win32pipe.PIPE_ACCESS_DUPLEX| # read/write access 
     win32file.FILE_FLAG_OVERLAPPED, 
     win32pipe.PIPE_TYPE_MESSAGE| # message-type pipe 
     win32pipe.PIPE_WAIT,   # blocking mode 
     1,        # number of instances 
     512,       # output buffer size 
     512,       # input buffer size 
     2000,       # client time-out 
     None)       # no security attributes 
    self.buffer = win32file.AllocateReadBuffer(512) 
    self.state='noconnected' 
    self.chstate() 

def execmsg(self): 
    "Translate the received message" 
    pass 

def chstate(self): 
    "Change the state of the pipe depending on current state" 
    if self.state=='noconnected': 
     win32pipe.ConnectNamedPipe(self.hpipe,self.over) 
     self.state='connectwait' 
     return -6 

    elif self.state=='connectwait': 
     j,self.strbuf=win32file.ReadFile(self.hpipe,self.buffer,self.over) 
     self.state='readwait' 
     return -6 

    elif self.state=='readwait': 
     size=win32file.GetOverlappedResult(self.hpipe,self.over,1) 
     self.msg=self.strbuf[:size] 
     ret=self.execmsg() 
     self.state = 'noconnected' 
     win32pipe.DisconnectNamedPipe(self.hpipe) 
     return ret 
+0

¡Genial! Gracias, he oído hablar de tuberías con nombre, pero nunca he trabajado con ellas, ¡tendré que comprobarlo! – monkut

+0

Esta respuesta no está clara. ¿Puedes explicarme cómo usar estas clases? un ejemplo sería bienvenido. – MikeTeX

+0

@MikeTex El código es solo un fragmento de un programa más grande, no un ejemplo. Puede escribir y (leer) de forma asincrónica a (desde) la canalización con nombre, utilizando eventos con win32event.WaitForMultipleObjects() para gestionar la sincronización. – gimel

2

XML/JSON y un servicio web o directamente a través de un socket. También es independiente del lenguaje y la plataforma, por lo que si decides que deseas alojar la parte de python en UNIX, puedes hacerlo, o si quieres usar Java o PHP de forma repentina o casi cualquier otro idioma que puedas.

Como regla general, los protocolos/arquitecturas propietarios como COM ofrecen más restricciones que beneficios. Esta es la razón por la cual las especificaciones abiertas aparecieron en primer lugar.

HTH

0

No debería ser demasiado complicado para configurar una prueba para cada una de sus alternativas y hacer un punto de referencia. Nota: supera los datos empíricos sensibles al contexto ... :)

Ah, y si haces esto, estoy seguro de que mucha gente estaría interesada en los resultados.

+0

Hasta que sepamos más información, esta es una respuesta muy sensata. –

2

+1 en las canalizaciones con nombre, pero también me gustaría añadir que a partir de sus comentarios parece que su aplicación es muy hablador. Cada vez que realiza una llamada remota, sin importar qué tan rápido sea el transporte subyacente, tiene un costo fijo de recopilación de datos y conexión. Puede ahorrar una gran cantidad de sobrecarga si cambia el método addpoint (lat, long) a un método addpoints (point_array). La idea es similar a por qué tenemos grupos de conexiones de bases de datos y conexiones http-keep-alive. Cuantas menos llamadas reales hagas, mejor. Su solución COM existente puede ser lo suficientemente buena si solo puede limitar la cantidad de llamadas que realiza sobre ella.

+0

Hemos analizado esto, pero hemos tenido problemas de memoria al enviar grandes cantidades de datos. La cuestión de la memoria se puede mitigar en cierta medida mediante el envío de datos en bloques. ¿Hay una mejor manera? – monkut

Cuestiones relacionadas