求问怎么使用多线程让 tkinter 里的数字跳动? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
jin6220
V2EX    Python

求问怎么使用多线程让 tkinter 里的数字跳动?

  •  
  •   jin6220 2017-04-29 08:15:23 +08:00 8004 次点击
    这是一个创建于 3163 天前的主题,其中的信息可能已经有所发展或是发生改变。

    import tkinter

    import requests

    import threading

    from bs4 import BeautifulSoup

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36', 'Referer':'https://wallstreetcn.com/live/global' }

    def getprice(url):

     html=requests.get(url, headers=headers).text soup=BeautifulSoup(html,'lxml') price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div> return price 

    while True:

    g=getprice('https://wallstreetcn.com/markets/indices/GER30INDEX') top = tkinter.Tk() label = tkinter.Label(top,text=g) label.pack() tkinter.mainloop() top.wm_attributes('-topmost',1) 
    15 条回复    2017-04-29 10:17:28 +08:00
    jin6220
        1
    jin6220  
    OP
       2017-04-29 08:18:23 +08:00
    不太会 md 格式 找了个网站贴了代码进去 然后所见所得修改了下贴进来 确实是好看了点
    昨天试了大半天 看了多进程 多线程 锁 队列 但是还是写不出来
    icedx
        2
    icedx  
       2017-04-29 08:19:00 +08:00 via Android
    印象里不能用 while true

    会阻塞界面的绘制
    jin6220
        3
    jin6220  
    OP
       2017-04-29 08:23:37 +08:00
    @icedx 哦 那是不是把 getprice 放进多线程里?通过队列取出这个返回值,但是昨天试了一天还是不成功;或者其他方法怎么实现呐
    icedx
        4
    icedx  
       2017-04-29 08:25:12 +08:00 via Android
    对的
    zjqzxc
        5
    zjqzxc  
       2017-04-29 08:49:48 +08:00
    当然是多线程,在线程中完成对主界面的更新工作

    getprice 操作放进新线程里,每次需要绘制的时候执行一次,修改对应的 label 的 text 属性即可
    jin6220
        6
    jin6220  
    OP
       2017-04-29 08:52:06 +08:00
    import tkinter
    import requests
    import threading
    from bs4 import BeautifulSoup
    import queue #import Queue

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
    'Referer':'https://wallstreetcn.com/live/global'
    }
    def getprice(url):
    html=requests.get(url, headers=headers).text
    soup=BeautifulSoup(html,'lxml')
    price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div>
    q.put(price)
    return price

    while True:
    q = queue.Queue()
    p = threading.Thread(target=getprice,args=('https://wallstreetcn.com/markets/indices/GER30INDEX',))
    p.start()

    qprice=q.get()
    top = tkinter.Tk()
    label = tkinter.Label(top,text=qprice)
    label.pack()
    tkinter.mainloop()
    top.wm_attributes('-topmost',1)
    写了个 不知道这个爬虫网页价格放到 tk 里随价格变化而变化,实现了没。
    jin6220
        7
    jin6220  
    OP
       2017-04-29 08:57:21 +08:00
    @zjqzxc 您意思是绘制的 tk 也放进一个线程了吗? 6 楼那个怎么样?刚才试了可以显示价格,不知道堵塞没,但是功能太简单了。还想实现这些:价格有变化绘制 tk,没变化不用管。
    zjqzxc
        8
    zjqzxc  
       2017-04-29 09:05:05 +08:00
    from tkinter import *
    import threading
    import time

    root = Tk()
    label1 = Label(root,text='0')
    label1.pack()

    def getPrice():
    return time.time()

    def threadGetPrice():
    while(True):
    label1['text'] = getPrice()
    time.sleep(1)

    t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh')
    t.setDaemon(True)
    t.start()

    root.mainloop()

    大概是这么个意思
    如果想实现价格变化时绘制(修改 text ),可以在 threadGetPrice()中进行判断
    jin6220
        9
    jin6220  
    OP
       2017-04-29 09:08:33 +08:00
    while 循环一次:构建队列,获取价格并放进队列,然后取出价格并绘制图形界面。
    想实现价格有变化绘制图形,没变化不要管看来有点难度(针对我这种小白哈)
    因为每次循环都是一个新的队列一个, 新的价格啊
    zjqzxc
        10
    zjqzxc  
       2017-04-29 09:15:03 +08:00
    @jin6220 如果只是为了修改界面上的价格,完全没必要使用队列。

    简单的思路是,有一个线程,在 while true:中获取最新价格,然后看是否改变了决定要不要更新主界面对应的 label 标签的 text 值;循环最后加一个 time.sleep(1)每次获取操作间隔 1 秒

    另外:新建线程的操作不要放在 while 中。。更新操作交给新创建的线程来做
    zjqzxc
        11
    zjqzxc  
       2017-04-29 09:25:52 +08:00   1
    import time
    import tkinter
    import requests
    import threading
    from bs4 import BeautifulSoup

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
    'Referer':'https://wallstreetcn.com/live/global'
    }
    def getPrice(url):
    (space)html=requests.get(url, headers=headers).text
    (space)soup=BeautifulSoup(html,'lxml')
    (space)price=soup.find('div',class_='price lt').get_text()
    (space)return price

    root = tkinter.Tk()
    label1 = tkinter.Label(root,text='init...')
    label1.pack()

    def threadGetPrice():
    (space)while(True):
    (space)(space)label1['text'] = getPrice('https://wallstreetcn.com/markets/indices/GER30INDEX')
    (space)(space)time.sleep(5)

    t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh')
    t.setDaemon(True)
    t.start()

    root.mainloop()
    jin6220
        12
    jin6220  
    OP
       2017-04-29 09:36:20 +08:00
    @zjqzxc 嗯请问下 t.setDaemon(True) 这个是不是更新线程的操作,查了下说这是设置守护线程,如果是更新线程的话,为什么 def threadGetPrice()函数下面还要加一句 while True 呐,
    jin6220
        13
    jin6220  
    OP
       2017-04-29 09:39:55 +08:00
    感觉到了进程 线程 这里 明显到了 python 的易学难精的地方了。。。
    感觉大山来了 当初类 实例之类的马马虎虎地啃下来算是能看懂别人写的代码
    但是进程 线程 锁之类的东西 完全看不懂 自猜: 好像搞懂 python 的运行机制才能玩转这些东西了 :)
    jin6220
        14
    jin6220  
    OP
       2017-04-29 10:11:15 +08:00
    @zjqzxc 有点理解那个 while true 了 交作业了 只能等到周一看行不行了 这样就能桌面显示了

    zjqzxc
        15
    zjqzxc  
       2017-04-29 10:17:28 +08:00
    @jin6220 这个 setDaemon 的作用并不是让代码循环执行。没有 while true,threadGetPrice()里的代码将只执行一次;
    setDaemon(True)的作用:父线程启动了子线程,当父线程结束,子线程跟着同时被 kill;
    setDaemon(False)的作用:父线程启动了子线程,当父线程结束,会等待子线程结束后,主线程才会结束;

    如果把 setDaemon 改为 false,关闭窗体后 threadGetPrice ()继续执行,但此时主窗体已经不存在了,执行更新操作时会报错;

    为啥会发生这个,具体原因我也没有确切答案。
    猜测可能的原因是,tkinter 窗口的线程并不是手动创建的线程的父线程,关闭 tkinter 窗体的操作并不会等待手动创建的线程结束,所以就有问题了;
    表现是:如果 setDaemon ( False ),关闭窗体后进程并不会立刻终止,而是等子线程完成后才会终止。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2517 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 15:08 PVG 23:08 LAX 07:08 JFK 10:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86