Я пытаюсь получить поток Python ReactiveX (используя библиотеку RxPy) для отправки в javascript на компонент веб-интерфейса, но, похоже, не могу найти способ сделать это. Кроме того, мне может понадобиться получить поток данных, поступающий в Javascript, в своего рода RxJS Observable для дальнейшей обработки. Не могли бы вы помочь мне понять, как этого добиться? Я до сих пор овладеваю ReactiveX, поэтому, может быть, мне не хватает некоторых фундаментальных концепций, но я изо всех сил пытаюсь найти что-то подобное в сети.
Эта проблема возникла, когда я работаю над настольным приложением, которое берет данные из конечной точки csv или zeromq и передает их в пользовательский интерфейс, где данные будут отображаться динамически (график обновляется как новыйданные поступают). Я использую Electron для создания своего приложения, используя Python в качестве внутреннего кода. Python является обязательным условием, так как я буду расширять приложение некоторыми моделями TensorFlow.
После действительно хорошо сделанного примера в качестве исходной структуры, я написал некоторый пример кода для игры, но яне могу заставить его работать. Мне удается добраться от кнопки пользовательского интерфейса до сценариев Python, но я застрял в возвращении метода PricesApi.get_stream (...).
index.html
Внешний интерфейс - прямой.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron Application</title>
</head>
<body>
<button id="super-button">Trigger Python Code</button>
<div id="py-output">
</div>
</body>
<script src="renderer.js" ></script>
</html>
api.py:
Файл сервера ZeroRPC похож на файл ввышеупомянутая ссылка.
import gevent
import json
import signal
import zerorpc
from core_operator import stream
class PricesApi(object):
def get_stream(self, filename):
return stream(filename)
def stop(self):
print('Stopping strategy.')
def echo(self, text):
"""echo any text"""
return text
def load_settings():
with open('settings.json') as json_settings:
settings_dictionary = json.load(json_settings)
return settings_dictionary
def main():
settings = load_settings()
s = zerorpc.Server(PricesApi())
s.bind(settings['address'])
print(f"Initialising server on {settings['address']}")
s.run()
if __name__ == '__main__':
main()
core_operator.py
Это файл, в котором основная логика будет сидеть для получения цен по подписке zeroMQ, но в настоящее время просто создает Observable из CSV.
import sys
import rx
from csv import DictReader
def prepare_csv_timeseries_stream(filename):
return rx.from_(DictReader(open(filename, 'r')))
def stream(filename):
price_observable = prepare_csv_timeseries_stream(filename)
return price_observable
rendered.js
наконец, JavaScript, который должен получать поток:
const zerorpc = require('zerorpc');
const fs = require('fs')
const settings_block = JSON.parse(fs.readFileSync('./settings.json').toString());
let client = new zerorpc.Client();
client.connect(settings_block['address']);
let button = document.querySelector('#super-button');
let pyOutput = document.querySelector('#py-output');
let filename = '%path-to-file%'
button.addEventListener('click', () => {
let line_to_write = '1'
console.log('button click received.')
client.invoke('get_stream', filename, (error, result) => {
var messages = pyOutput;
message = document.createElement('li'),
content = document.createTextNode(error.data);
message.appendChild(content);
messages.appendChild(message);
if(error) {
console.error(error);
} else {
var messages = pyOutput;
message = document.createElement('li'),
content = document.createTextNode(result.data);
message.appendChild(content);
messages.appendChild(message);
}
})
})
Я изучал использование WebSockets, но не смог понятькак это реализовать. Я нашел несколько примеров использования сервера Tornado, однако я стараюсь сохранить его как можно более чистым, и, кроме того, мне кажется странным, что, имея уже структуру клиент / сервер от Electron, я не могу использовать это напрямую. Также я пытаюсь сохранить всю систему в виде структуры PUSH, поскольку требования к данным не позволяют использовать шаблон типа PULL с регулярными опросами и т. Д.
Большое спасибо заранее за любое время, когда вы можетевыделите это, и, пожалуйста, дайте мне знать, если вам потребуются какие-либо дополнительные детали или объяснения.