Как связать метод ws.run_forever () и передать данные в другой цикл в приложении с графическим интерфейсом - PullRequest
0 голосов
/ 03 июля 2019

ПРИМЕЧАНИЕ. В процессе сокращения кода перед загрузкой вопроса я фактически исправил его сам, и теперь он делает то, что мне нужно.Я по-прежнему буду загружать это на тот случай, если в будущем у кого-то возникнет тот же вопрос, и вместо этого попросить совета по улучшению моей реализации, поскольку я новичок в программировании.Я отмечу это как решенное после получения некоторых отзывов о передовых методах.

Сводка Я пытаюсь реализовать API-интерфейс Websocket в JSON-RPC2.0, который направляет помещенные данные в мойКласс приложения.Этот API предназначен для японского криптообмена под названием bitFlyer, и документацию по API можно найти здесь , если необходимо.

Этот класс работает независимо, и я могу видеть данные в журнале,Графический интерфейс также работает независимо и циклически обновляет.Однако у меня возникают проблемы с получением потоков для работы с моим классом графического интерфейса, когда я пытаюсь объединить их в единое целое.

Попытки решения Я перепробовал ряд предлагаемых решений, но никогда не смог пройти мимопетля websocket с моими подходами до сих пор.Это уменьшенная версия моего кода ниже, и это должно быть копирование / вставка для Python 3.7.

Найденное решение Мне нужно было создать поток для потока данных перед запуском графического интерфейса пользователя.Loop.Я все еще хотел бы знать, как создавать потоки для основного цикла графического интерфейса пользователя в образовательных целях (на случай, если мне понадобится сделать это в будущем), но выдает ошибку, когда я пытаюсь создать поток.

import json as js
import websocket
from logging import getLogger,INFO,StreamHandler
from threading import Thread
from tkinter import *

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(INFO)
logger.setLevel(INFO)
logger.addHandler(handler)

"""
This program calls Bitflyer real time API JSON-RPC2.0 over Websocket
"""
class RealtimeAPI(Thread):
    def __init__(self, url, channel):
        self.url = url
        self.channel = channel

        #Define Websocket
        self.ws = websocket.WebSocketApp(self.url,header=None,on_open=self.on_open, on_message=self.on_message, on_error=self.on_error, on_close=self.on_close)
        websocket.enableTrace(True)


    def run(self):
        #ws has loop. To break this press ctrl + c to occur Keyboard Interruption Exception.
        Thread(target=self.ws.run_forever).start()
        logger.info('Web Socket process ended.')

    """
    Below are callback functions of websocket.
    """
    # when we get message
    def on_message(self, ws, message):
        output = js.loads(message)['params']
        logger.info(output)
        message = (jsonparse(output, 'message'))
        app.mid_price.set(jsonparse(message, 'mid_price'))

    # when error occurs
    def on_error(self, ws, error):
        logger.error(error)

    # when websocket closed.
    def on_close(self, ws):
        logger.info('disconnected streaming server')

    # when websocket opened.
    def on_open(self, ws):
        logger.info('connected streaming server')
        output_json = js.dumps(
            {'method' : 'subscribe',
            'params' : {'channel' : self.channel}
            }
        )
        ws.send(output_json)

UPDATE_RATE = 1000

class Application(Frame):
    global beginupdate
    beginupdate = False

    def __init__(self, master):
        """ Initialize the frame """
        Frame.__init__(self, master)
        self.grid()
        self.create_widgets()
        self.updater()

    def create_widgets(self):
        # ********** Main window **********
        self.mainwindow = Frame(self, bg='black')

        self.mid_price = IntVar()
        self.label_1 = Label(self.mainwindow, text='Mid price(JPY)', fg='gray', bg='black', bd=1, relief=SUNKEN, anchor=W)
        self.label_2 = Label(self.mainwindow, textvariable=self.mid_price, fg='gray', bg='black', bd=1, relief=SUNKEN,
                             anchor=W)
        self.label_1.grid(row=1, sticky=NSEW)
        self.label_2.grid(row=2, sticky=NSEW)

        self.mainwindow.pack(side=TOP, anchor=W)

    def update_something1(self):
        if beginupdate:
            donothing()
        print('Updated')

    def updater(self):
        global beginupdate

        self.update_something1()
        beginupdate = True
        self.after(UPDATE_RATE, self.updater)

def jsonparse(json, mainterm='', value='', nestedterm=''):
    if mainterm == '':
        return json
    elif value == '':
        return json[mainterm]
    else:
        for i in json:
            if i[mainterm] == value:
                return i[nestedterm]

def donothing():
    print("ok ok I won't")


if __name__ == '__main__':
    #API endpoint

    url = 'wss://ws.lightstream.bitflyer.com/json-rpc'
    channel = 'lightning_board_snapshot_BTC_JPY'

    root = Tk()
    root.configure(background='black')
    root.geometry('100x100')

    app = Application(root)
    app.pack(fill="both", expand=True)

    json_rpc = RealtimeAPI(url=url, channel=channel)

    Thread(target=json_rpc.run).start()  # Websocket data stream loop
    root.mainloop() # GUI Main Loop

Ожидание Обновление метки при поступлении новых данных из потока данных веб-сокета

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...