質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
bitFlyer API

bitFlyer APIは、仮想通貨取引所bitFlyerが公開しているAIPツール。bitFlyer Lightning/API playground/chainFlyer/Echoの4種類あり、bitFlyerソフトをカスタマイズすることが可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Q&A

解決済

1回答

1498閲覧

bitflyer Realtime APIに、websocketで接続して得たデータを変数に格納する

161

総合スコア1

bitFlyer API

bitFlyer APIは、仮想通貨取引所bitFlyerが公開しているAIPツール。bitFlyer Lightning/API playground/chainFlyer/Echoの4種類あり、bitFlyerソフトをカスタマイズすることが可能です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

0グッド

0クリップ

投稿2022/08/21 11:42

編集2022/08/22 21:02

前提

bitflyer Realtime APIに、websocketで接続して得たデータを変数に格納するために
試行錯誤しましたが、やり方がわかりませんでした

実現したいこと

bitflyer Realtime APIに、websocketで接続して得たデータを変数に格納する

発生している問題・エラーメッセージ

--- Logging error ---
Traceback (most recent call last):
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 383, in run_forever
dispatcher.read(self.sock.sock, read, check)
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 64, in read
r = self.select()
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 78, in select
r = sel.select(self.ping_timeout)
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/selectors.py", line 562, in select
kev_list = self._selector.control(None, max_ev, timeout)
KeyboardInterrupt

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 424, in _callback
callback(self, *args)
TypeError: on_close() takes 2 positional arguments but 4 were given

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/logging/init.py", line 1086, in emit
stream.write(msg + self.terminator)
AttributeError: 'int' object has no attribute 'write'
Call stack:
File "/Users/a1/Desktop/ml/main.py", line 14, in <module>
json_rpc = RealtimeAPI(url=url, channel=channel)
File "/Users/a1/Desktop/ml/bitflyer.py", line 15, in init
self.connect()
File "/Users/a1/Desktop/ml/bitflyer.py", line 22, in connect
self.ws.run_forever()
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 390, in run_forever
teardown()
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 318, in teardown
self._callback(self.on_close, close_status_code, close_reason)
File "/Users/a1/opt/anaconda3/envs/m/lib/python3.9/site-packages/websocket/_app.py", line 429, in _callback
self.on_error(self, e)
File "/Users/a1/Desktop/ml/bitflyer.py", line 35, in on_error
logger.error(error)
Message: TypeError('on_close() takes 2 positional arguments but 4 were given')
Arguments: ()

該当のソースコード

使用言語 python3.9

コード ファイル名 bitflyer.py

import logging import websocket import json import pybitflyer logger = logging.getLogger(__name__)#logging ticker_data = 0#追記 class RealtimeAPI(object): def __init__(self, url, channel): self.url = url self.channel = channel self.connect() def connect(self): 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) self.ws.run_forever() logger.info('Web Socket process ended.') """ Below are callback functions of websocket. """ # when we get message def on_message(self, ws, message): resp = json.loads(message)['params']['message'] self.set_realtime_ticker(resp) # 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') input_data = json.dumps( {'method' : 'subscribe', 'params' : {'channel' : self.channel} } ) ws.send(input_data) def set_realtime_ticker(self, resp): timestamp = resp['timestamp'] product_code = resp['product_code'] volume = float(resp['volume']) ticker = [product_code, timestamp, volume] print(ticker) logger.info(f'ticker={ticker}') global ticker_data#追記 ticker_data = ticker#追記 print(ticker_data)#ここにAPIから入ってくるtickerのデータを入れたいです ---------------------------------ここからもう一つのファイル--------------------------------------- #ファイル名 main.py import logging import sys from bitflyer import RealtimeAPI logging.basicConfig(level=logging.INFO, stream=sys.stdout) # logging.basicConfig(level=logging.INFO, stream=a) #ログレベル INFO 出力先 stream=sys.stdout if __name__ == "__main__": url = "wss://ws.lightstream.bitflyer.com/json-rpc" channel = "lightning_ticker_FX_BTC_JPY" json_rpc = RealtimeAPI(url=url, channel=channel) ------------------------------コードはここまで--------------------------------------- ### 試したこと ①ファイル名bitflyer.pyのdef set_realtime_tickerにあるtickerをグローバル変数にした ②ファイル名 main.pyのlogging.basicConfigにあるstream=変数にした ### 補足情報(FW/ツールのバージョンなど) Visual Studio Codeを使用しています ここにより詳細な情報を記載してください。 よろしくお願いいたします

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/08/21 12:02

「変数に格納する」とは、具体的にいうと、質問に記載されているソースコードの中のどの変数を、どのようにしたいのでしょうか? 手元でbitflyer.pyとmain.pyを同じディレクトリに配置してmain.pyを実行したところ、tickerの内容は正常にターミナルに表示されました。
161

2022/08/21 12:30

追記依頼いただき、ありがとうございます 仰る通りターミナルに表示されるところまではできています そのターミナルに表示されているデータを、コード中には記入していないのですが ファイル名 bitflyer.py の def set_realtime_ticker内に tick_data=ticker として変数 tick_data 内に格納し それを関数の外でも使えるグローバル変数として使用したいと考えています
退会済みユーザー

退会済みユーザー

2022/08/21 13:08

「それを関数の外でも使えるグローバル変数として使用したいと考えています」 →これは、何も情報を持っていない人から見ると、手掛かりがなく答えようがありません。 というか範囲が広すぎます。 エスパーを駆使して具体的なシチュエーションを勝手に作って例示することはできなくもないですが、仮にそれが質問者さんの解決したいことではなかった場合、無駄打ちになってしまいます。 (よくある「XY問題」というものに近いです) 「(グローバル変数などにすることによって)どのように使いたいのか」という「使い方」を具体的なコードも含めて、質問文に書いてください。 つまり「このようなコードで、こういう風にtickerを取り出して、このように加工したいと考えているが、現状できない」というのがわかる内容(コード)、ということです。 動かないコードでも構いません。そのコードを動かしてエラーが出ているならばそのエラーも省略せずに記載してください。
161

2022/08/22 01:11 編集

内容を修正しました、コードの変更(ファイル名 bitflyer.pyの#追記となっている部分と、最終行) とコード変更に伴って生じたエラーを記載しました よろしくお願いいたします
guest

回答1

0

ベストアンサー

コメントによるヒヤリングを経た結果、結局
「print(ticker_data)」のticker_dataにデータを入れたい」ということでした。

print と組み合わせていることから読み解くに
多分「bitflyer.py の中(下の方)に、print(ticker_data)
のような形で書いてticker_data の"内容を表示したい”」
と理解しました。

これは、下記のようにマルチスレッドを使用し、キューを使って受け渡しすればできます。

なお、下記の場合 main.py は無関係になるので、main.py の実行は不要であり、
bitflyer.py を実行すればよいです。
(「bitflyer.py の中(下の方)に」print(ticker_data)と入れてticker_data の内容を表示したい、とのことですから当然といえば当然ですが)

bitflyer.py

py

1import logging 2import json 3import sys 4import time 5import websocket 6from concurrent.futures import ThreadPoolExecutor 7from queue import Queue 8 9logging.basicConfig(level=logging.INFO, stream=sys.stdout) 10logger = logging.getLogger(__name__) 11 12que = Queue() # データ受け渡しのためのキュー 13stop = {"status":False} # 停止するためのフラグ 14 15 16class RealtimeAPI(object): 17 18 def __init__(self, url, channel): 19 self.url = url 20 self.channel = channel 21 self.connect() 22 23 def connect(self): 24 self.ws = websocket.WebSocketApp\ 25 (self.url,header=None,on_open=self.on_open,\ 26 on_message=self.on_message, on_error=self.on_error,\ 27 on_close=self.on_close) 28 self.ws.run_forever() 29 logger.info('Web Socket process ended.') 30 31 """ 32 Below are callback functions of websocket. 33 """ 34 # when we get message 35 def on_message(self, ws, message): 36 resp = json.loads(message)['params']['message'] 37 self.set_realtime_ticker(resp) 38 39 if stop["status"]: 40 # 停止フラグがTrueならwebsocketをクローズする。 41 self.ws.close() 42 43 # when error occurs 44 def on_error(self, ws, error): 45 logger.error(error) 46 47 # when websocket closed. 48 def on_close(self, ws): 49 logger.info('disconnected streaming server') 50 51 # when websocket opened. 52 def on_open(self, ws): 53 logger.info('connected streaming server') 54 input_data = json.dumps( 55 {'method' : 'subscribe', 56 'params' : {'channel' : self.channel} 57 } 58 ) 59 ws.send(input_data) 60 61 def set_realtime_ticker(self, resp): 62 timestamp = resp['timestamp'] 63 product_code = resp['product_code'] 64 volume = float(resp['volume']) 65 ticker = [product_code, timestamp, volume] 66 que.put(ticker) #キューに ticker を入れる。 67 68 69def task(): 70 url = "wss://ws.lightstream.bitflyer.com/json-rpc" 71 channel = "lightning_ticker_FX_BTC_JPY" 72 RealtimeAPI(url=url, channel=channel) 73 74 75executor = ThreadPoolExecutor() 76executor.submit(task) 77try: 78 while True: 79 # キューから ticker を取り出す。 80 ticker_data = str(que.get()) 81 print(ticker_data) # ここでAPIから入ってくるtickerのデータを表示 82 time.sleep(1) 83except KeyboardInterrupt: 84 stop["status"] = True 85 executor.shutdown() 86

停止する場合はCTRL+Cを押してください。
止めることができなくても構わない、というなら try ~ except で囲まなくてもいいですが・・・。


分割例

仮に bitflyer.py と main.py を分割して、main.pyだけ実行して同じようなことがしたいなら、下記のようになります。

bitflyer.py

py

1import json 2import logging 3import sys 4import websocket 5from queue import Queue 6 7logging.basicConfig(level=logging.INFO, stream=sys.stdout) 8logger = logging.getLogger(__name__) 9 10que = Queue() # データ受け渡しのためのキュー 11 12stop = {"status":False} # 停止するためのフラグ 13 14 15class RealtimeAPI(object): 16 17 def __init__(self, url, channel): 18 self.url = url 19 self.channel = channel 20 self.connect() 21 22 def connect(self): 23 self.ws = websocket.WebSocketApp\ 24 (self.url,header=None,on_open=self.on_open,\ 25 on_message=self.on_message, on_error=self.on_error,\ 26 on_close=self.on_close) 27 self.ws.run_forever() 28 logger.info('Web Socket process ended.') 29 30 """ 31 Below are callback functions of websocket. 32 """ 33 # when we get message 34 def on_message(self, ws, message): 35 resp = json.loads(message)['params']['message'] 36 self.set_realtime_ticker(resp) 37 38 if stop["status"]: 39 # 停止フラグがTrueならwebsocketをクローズする。 40 self.ws.close() 41 42 # when error occurs 43 def on_error(self, ws, error): 44 logger.error(error) 45 46 # when websocket closed. 47 def on_close(self, ws): 48 logger.info('disconnected streaming server') 49 50 # when websocket opened. 51 def on_open(self, ws): 52 logger.info('connected streaming server') 53 input_data = json.dumps( 54 {'method' : 'subscribe', 55 'params' : {'channel' : self.channel} 56 } 57 ) 58 ws.send(input_data) 59 60 def set_realtime_ticker(self, resp): 61 timestamp = resp['timestamp'] 62 product_code = resp['product_code'] 63 volume = float(resp['volume']) 64 ticker = [product_code, timestamp, volume] 65 que.put(ticker) #キューに ticker を入れる。

main.py

py

1import time 2from concurrent.futures import ThreadPoolExecutor 3from bitflyer import RealtimeAPI, que, stop 4 5 6def task(): 7 url = "wss://ws.lightstream.bitflyer.com/json-rpc" 8 channel = "lightning_ticker_FX_BTC_JPY" 9 RealtimeAPI(url=url, channel=channel) 10 11if __name__ == "__main__": 12 executor = ThreadPoolExecutor() 13 executor.submit(task) 14 try: 15 while True: 16 # キューから ticker を取り出す。 17 ticker_data = str(que.get()) 18 print(ticker_data) # ここでAPIから入ってくるtickerのデータを表示 19 time.sleep(1) 20 except KeyboardInterrupt: 21 stop["status"] = True 22 executor.shutdown()

投稿2022/08/22 11:02

編集2022/08/22 12:00
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

161

2022/08/22 12:02

ご回答をいただき感謝しています ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問