Как перенести базовые объекты между Ruby и Python? - PullRequest
6 голосов
/ 22 января 2011

В настоящее время я использую JSON в качестве формата сериализации для передачи простого хэша, содержащего строки, числа и массив из Ruby, в скрипт Python:

IO.popen('./convert.py', 'w') do |w|
    w.write({ :height => height, :width => width, :id => job_id, :data => pix }.to_json)
    w.write "\n"
    w.close_write
end

В этом случае height, width и job_id - все числа, а pix - массив массивов целых чисел.

Это скрипт Python, который он запускает:

#!/usr/bin/env python

from PIL import Image
import json
import sys

output = json.load(sys.stdin)

width = output['width']
height = output['height']
name = 'images/' + str(output['id']) + '/image.bmp'
data = [ tuple(datum) for datum in output['data'] ]

img = Image.new("RGB", (width, height))

img.putdata(data)

img.save(name)

Небольшое быстрое тестирование с использованием массива с 3,9 миллионами значений (вероятно, примерно 1/4 от размера, который будет обычно использоваться) показало, что сценарий занимает около 105 секунд, и 90 секунд со всеми строками ниже output = ... с комментариями из. Очевидно, было бы хорошо, если бы для сериализации не потребовалось 85% времени обработки такого простого сценария.

Единственный способ ускорить это, о котором я могу подумать, - это найти некоторую форму двоичной сериализации / маршалинга, которую можно использовать для передачи данных из Ruby в Python. К сожалению, я не смог найти ни одной такой системы, только RMarshal , которая, кажется, могла бы работать по-другому.

Ответы [ 2 ]

9 голосов
/ 22 января 2011

Может быть MessagePack - это то, что нужно.Существуют привязки для нескольких языков, включая Ruby и Python.

2 голосов
/ 22 января 2011

Очевидно, что создание и (особенно) разбор JSON можно улучшить, поскольку простой пользовательский формат приводит к огромным различиям, не прибегая к нетекстовому формату.Мне пришлось изменить ваше использование putdata (в частности, формат данных, передаваемых в него), в противном случае приведенный ниже тест существенно не отличается.

$ time ./gen-json.py 1500 900 json | ./read-json.py 

real    0m50.727s
user    0m50.131s
sys     0m0.164s
$ time ./gen.py 1500 900 custom | ./read.py 

real    0m3.786s
user    0m6.076s
sys     0m0.064s

Простите за общее хакерство в них, как они были написаны воколо 5 минут, чтобы начать определять, в чем проблема.Тем не менее, все, кажется, работает в них хорошо;по крайней мере, я могу открыть созданные BMP.:)

gen-json.py

#!/usr/bin/env python2.6
import sys

width, height, img_id = sys.argv[1:]
width = int(width)
height = int(height)
print """{"width": %s, "height": %s, "id": "%s", "data": [""" % (width, height, img_id)
row = str([0 for _ in xrange(width)])
first = True
for _ in xrange(height):
  if first:
    first = False
  else:
    print ","
  print row,
print "]}"

read-json.py

#!/usr/bin/env python2.6
import json
import sys
from PIL import Image

output = json.load(sys.stdin)

width = output['width']
height = output['height']
name = 'image-%s.bmp' % output['id']
data = []
assert len(output['data']) == height
for x in output['data']:
  assert len(x) == width
  data.extend(x)

img = Image.new("RGB", (width, height))
img.putdata(data)
img.save(name)

gen.py

#!/usr/bin/env python2.6
import sys

width, height, img_id = sys.argv[1:]
width = int(width)
height = int(height)
print img_id, width, height
for _ in xrange(height):
  for _ in xrange(width):
    print 0,
  print

read.py

#!/usr/bin/env python2.6
import sys
from PIL import Image

img_id, width, height = raw_input().split()
width = int(width)
height = int(height)
name = "image-%s.bmp" % img_id
data = [int(x) for row in sys.stdin for x in row.split()]
assert len(data) == width * height

img = Image.new("RGB", (width, height))
img.putdata(data)
img.save(name)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...