PySimpleGUI点击按钮无法触发绑定的Coinbase下单函数问题
问题描述
基于Coinbase Crypto Exchange沙箱API开发了加密货币市价单交易程序,无GUI场景下代码运行完全正常。为提升易用性,计划开发图形界面,实现点击按钮即可触发对应功能,无需逐行运行代码。
完成基础GUI开发、将市价买入逻辑封装为独立函数后,无法通过界面按钮触发交易执行。已尝试调整函数调用位置、修改代码排布顺序,甚至将全部相关代码移入买入函数中,问题仍未解决。初步猜测买入订单无法执行是买入逻辑代码与其余代码分离导致,验证后该假设不成立。
客户端初始化代码
import pandas as pd import cbpro import PySimpleGUI as sg api_secret = # 需填入自身API密钥 api_key = # 需填入自身API密钥 api_pass = # 需填入自身API密码 # 创建API客户端 url='https://api-public.sandbox.pro.coinbase.com' client = cbpro.AuthenticatedClient( api_key, api_secret, api_pass, api_url=url )
行情WebSocket获取代码
#websocket class TextWebsocketClient(cbpro.WebsocketClient): # 连接建立逻辑 def on_open(self): self.url = 'wss://ws-feed-public.sandbox.pro.coinbase.com' # 连接端点 self.message_count = 0 # 消息接收逻辑 def on_message(self,msg): self.message_count += 1 msg_type = msg.get('type',None) if msg_type == 'ticker': # 提取需要的字段 time_val = msg.get('time',('-'*27)) price_val = msg.get('price',None) if price_val is not None: price_val = float(price_val) product_id = msg.get('product_id',None) print(f"{time_val:40} {price_val:.3f} {product_id}\tchannel type: {msg_type}") def on_close(self): print(f"<---Websocket connection closed--->\n\tTotal messages: {self.message_count}") # 启动行情流,连接断开或主动关闭时停止 stream = TextWebsocketClient(products=['BTC-USD'],channels=['ticker']) stream.start() #stream.close() print ("Stream closed")
封装的市价买入函数
注:该段逻辑在非函数、非GUI场景下运行完全正常,封装为函数被GUI按钮调用时无法正常执行
# 市价买单下单 def buy(): client.place_market_order(product_id='BTC-USD',side='buy',funds=100) accounts = client.get_accounts() for acc in accounts: currency = acc.get('currency') if currency=='BTC': acc_id = acc.get('id') acc_history = client.get_account_history(acc_id) return "Buy Complete"
GUI界面代码
# GUI 布局 sg.theme('DarkGreen') layout = [ [sg.Text("Welcome to your Crypto Launch Pad!\n Select a command...")], [sg.Button('Buy')], [sg.Button('Sell')], [sg.Button('Current Price')], [sg.Button('Profit/Loss')], [sg.Button('Exit')] ] window = sg.Window('Crypto Buy/Sell Launch Pad', layout, size = (400, 400)) # 窗口标题 # 事件循环 while True: event, values = window.read() print(event, values) if event is None or event == "Exit": break if event == "Buy": # 绑定买入函数 buy() print(buy()) window.close()
排查方向与修复方案
- 核心问题:WebSocket阻塞主线程
cbpro库的WebsocketClient.start()方法默认以阻塞模式运行,会占用当前线程无限循环接收消息。按现有代码顺序,执行到stream.start()时就会卡住,后续GUI初始化、事件循环的代码根本不会执行。非GUI场景下是顺序执行逻辑,阻塞不影响后续下单操作,但GUI必须靠主线程持续运行事件循环才能响应按钮点击。修复方式是启动WebSocket时传入线程参数,让行情流在后台子线程运行:stream.start(threaded=True) - 缺少接口响应捕获,报错无感知
现有buy()函数没有接收下单接口的返回值,即使接口返回鉴权失败、参数错误、余额不足等报错,也不会有任何提示。建议先接收接口返回值打印排查:def buy(): order_resp = client.place_market_order(product_id='BTC-USD',side='buy',funds=100) print("下单接口返回:", order_resp) # 打印返回内容定位报错 # 后续逻辑不变 - 重复触发下单问题
GUI事件逻辑中连续调用了两次buy():一次直接调用,一次在print(buy())时又调用一次,会触发重复下单,删除其中一次调用即可。 - 变量作用域隐患
buy()函数中的acc_id变量仅在for循环匹配到BTC账户时才会赋值,如果接口返回的账户列表中没有BTC币种,后续调用get_account_history(acc_id)会直接触发未定义变量报错,建议提前初始化acc_id并加异常判断。
内容的提问来源于stack exchange,提问作者dingoyum
相关产品推荐
相关产品推荐

