Каков наилучший способ передачи данных из Python в другое приложение в Windows? - PullRequest
8 голосов
/ 13 ноября 2008

Я разрабатываю приложение с командой на .Net (C ++) и предоставляю COM-интерфейс для взаимодействия с python и другими языками.

Мы обнаружили, что передача данных через COM оказывается довольно медленной.

Я рассмотрел несколько альтернатив:

  • выгрузка данных в файл и отправка пути к файлу через com
  • Общая память через mmap ?
  • Потоковая передача данных через сокет напрямую?

По вашему опыту, как лучше всего передавать данные?

Ответы [ 4 ]

9 голосов
/ 13 ноября 2008

Оставаясь в рамках механизмов межпроцессного взаимодействия Windows, мы имели положительный опыт использования окон с именованными каналами . Использование перекрывающегося ввода-вывода Windows и модуля win32pipe из pywin32 .

Вы можете многое узнать о win32 и python в книге Программирование на Python на Win32 .

Отправляющая часть просто пишет в r'\\.\pipe\mypipe'.

Объект слушателя (ovpipe) содержит дескриптор события, и ожидание сообщения с возможными другими событиями включает вызов win32event.WaitForMultipleObjects.

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

Вот часть класса прослушивателя с перекрытием Python:

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
2 голосов
/ 13 ноября 2008

+ 1 на именованных каналах, но я также хотел бы добавить, что из ваших комментариев кажется, что ваше приложение очень болтливое. Каждый раз, когда вы делаете удаленный вызов, независимо от того, насколько быстрым является основной транспорт, у вас есть фиксированная стоимость маршалинга данных и установления соединения. Вы можете сэкономить огромные накладные расходы, если измените метод addpoint (lat, long) на метод addpoints (point_array). Идея похожа на то, почему у нас есть пулы соединений с базой данных и соединения http-keep-alive. Чем меньше реальных звонков вы делаете, тем лучше. Ваше существующее COM-решение может быть даже достаточно хорошим, если вы можете просто ограничить количество звонков, которые вы делаете по нему.

2 голосов
/ 13 ноября 2008

XML / JSON и веб-сервис или напрямую через сокет. Он также не зависит от языка и платформы, поэтому, если вы решите разместить часть Python в UNIX, вы можете это сделать, или если вы захотите внезапно использовать Java, PHP или почти любой другой язык, который сможете.

Как правило, проприетарные протоколы / архитектуры, такие как COM, предлагают больше ограничений, чем преимуществ. Вот почему открытые спецификации появились в первую очередь.

НТН

0 голосов
/ 13 ноября 2008

Не должно быть слишком сложно настроить тест для каждой из ваших альтернатив и выполнить тест. Отмечая бьющиеся контекстно-зависимые эмпирические данные ...:)

О, и если вы сделаете это, я уверен, что многие будут заинтересованы в результатах.

...