使用Python从Tkinter中的比特币交换API更新数据

时间:2014-10-22 01:48:50

标签: python api tkinter auto-update

我用Tkinter写了一个小程序,用不同的交换API打印出比特币的价格。我希望能够每x秒更新一次数据,但我无法弄清楚如何。我的猜测是我需要使用 .after( delay_ms, callback, args ) 方法。

我是对的吗?

# Python 2.7.6. Calling exchange APIs.
import time, json, requests

from Tkinter import *

root = Tk()

def bitstampUSD():  
    bitstampUSDTick = requests.get( 'https://www.bitstamp.net/api/ticker/' )
    return bitstampUSDTick.json()['last']

def btceUSD():
    btceBtcTick = requests.get( 'https://btc-e.com/api/2/btc_usd/ticker' )
    return btceBtcTick.json()['ticker']['last']

bitstampUSDLive = float( bitstampUSD() )
btceUSDLive     = float( btceUSD() )

photo        = PhotoImage( file = './images/blackcoin_500_small.gif' )
text1        = Text( root, height = 30, width = 31 )
text1.insert(       END,'\n' )
text1.image_create( END, image = photo )
text1.pack( side = LEFT )

text2        = Text( root, height = 30, width = 60 )
scroll       = Scrollbar( root, command = text2.yview )
text2.configure( yscrollcommand = scroll.set )
text2.tag_configure( 'bold_italics',  font = ( 'Arial',           12, 'bold', 'italic' ) )
text2.tag_configure( 'bold',          font = ( 'Arial',           12, 'bold' ) )
text2.tag_configure( 'big',           font = ( 'Verdana',         20, 'bold' ) )
text2.tag_configure( 'medium',        font = ( 'Verdana',         14, 'bold' ) )
text2.tag_configure( 'color',         font = ( 'Tempus Sans ITC', 12, 'bold' ), foreground = '#476042' )
text2.tag_bind( 'follow', '<1>', lambda e, t = text2: t.insert( END, "Not now, maybe  later!" ) )

text2.insert( END, '\nCrypto Price Ticker\n',    'big' )
text2.insert( END, "\nBitcoin Exchange Rates\n", "medium" )
text2.insert( END, "%.2f" % bitstampUSDLive )
text2.insert( END, " USD - Bitstamp\n" )
text2.insert( END, "%.2f" % btceUSDLive )
text2.insert( END, " USD - BTC-e\n" )
text2.pack(  side = LEFT )
scroll.pack( side = RIGHT, fill = Y )

root.mainloop()

2 个答案:

答案 0 :(得分:0)

是的,Tkinter .after()方法会(可能)有所帮助,但要小心。

Tkinter有一个非常强大的基于事件的内部和基于时间的调度服务。

在为混合GUI +非GUI活动设计基于时间和链接的调度方案时,应该小心谨慎。通常情况下,错链请求和/或不良调度逻辑可能会破坏/挂起Tkinter .mainloop()调度程序。

近乎实时的系统设计的一些先前经验将有助于实现响应式GUI部分和#34;良好涂油&#34; /错误处理的非GUI部分,不会使Tkinter .mainloop()和远程数据API提供程序失去稳定性。接口

.after( wms, TASK, *args ) # non-GUI, pure MVC-Controller time-based TASK scheduling
.after_idle( TASK, *args ) # IMPORTANT method to defer a TASK into MVC-idle-<STATE>
.after_cancel( aTaskID )   # IMPORTANT method to release a scheduled TASK
.update_idletasks()        # IMPORTANT method to enforce to process TASK(s) ( if any ) deferred into an idle-tasks-queue before next MVC-idle-<STATE>

在问题后面退步&#34;我是对的吗?&#34;

将Tkinter用于GUI层服务及其定时(调度)服务是一种常见的做法。

您的主要设计应将子任务分为事件驱动的控制模式(因为一旦您输入.mainloop(),这是您仍然可以控制非GUI的唯一手段。 背景&#34;活动)。

当您将流程重新设计为分离&#34;层中的处理控制时。 (其中只有一个是已经def - 背景的比特币交换API对话)你还需要提供手段&amp;控制更新到纯GUI - 代码的一部分(最有可能通过.StringVar()IntVar().BooleanVar().DoubleVar()及其相关的触发.trace_variable()工具

为了将非GUI异步事件作为代码驱动的Tkinter激励发送,还有一种强大的.event_generate( <eventNameId>, **args )方法。

良好的实时设计的另一个标志是它将减少流量。作为一个简单的例子,状态完整的设计将避免在所有情况下重新绘制GUI,其中没有从外部数据源检索或从内部处理中生成相同的值。

要求同步刷新或处理报价流?

总是有机会安排调用比特币交换API提供的值的同步刷新。在松散时序设计的情况下,这不会是一个麻烦。然而,走得更快将开始产生新的问题。一些技术(公平队列调度,传输延迟,响应端到端延迟)和一些非技术性。

对于远程报价流或报价发布API的处理,还可以记住官方条款和条款。适用于数据访问的条件。有些API有服务器端速率限制控制,有些没有,有些会默默地丢弃会话,有些会因为违反这些条款而将你列入黑名单。条件。

使用来自Exchange提供的报价流处理可以避免与条款和条款发生冲突。条件,在刷新率增加和/或时间紧张的情况下,如果在早期设计阶段没有得到应有的谨慎处理,每个条件都是常见的陷阱。

答案 1 :(得分:0)

是的,你是对的。如果要定期调用某个函数,请使用after,然后让函数使用after重新安排自己。

例如,如果您有一个名为getRates的函数,并且您想要大约每15秒调用一次,那么您可以像这样编写它:

def getRates():
    # put the code here to get the rates
    ...

    # call this function again as soon as possible after 15 seconds has elapsed
    root.after(15000, getRates)

第一次调用时,它将大约每15秒运行一次,直到您退出程序。

请记住,如果getRates速度很慢(并且可能是从Web服务获取数据),那么您的GUI可能会有无响应的时刻。如果是这种情况,您可以在线程中运行getRates函数,并将其写入线程安全队列。然后,您可以使用相同的技巧来从队列中提取最新数据并将其放入UI中。