简体   繁体   中英

Stop tweepy streaming in Tkinter

I am trying to stream tweets with python/tweepy using tkinter GUI. Ideally, I would have a "Start" button that would start the stream, and a "Stop" button that would stop the stream. The next example (from stackoverflow) shows in a simplified way what I try to achieve:

import Tkinter as tk
import threading

class App():
    def __init__(self, master):
        self.isrecording = False
        self.button1 = tk.Button(main, text='start')
        self.button2 = tk.Button(main, text='stop')

        self.button1.bind("<Button-1>", self.startrecording)
        self.button2.bind("<Button-1>", self.stoprecording)
        self.button1.pack()
        self.button2.pack()

    def startrecording(self, event):
        self.isrecording = True
        t = threading.Thread(target=self._record)
        t.start()

    def stoprecording(self, event):
        self.isrecording = False
        print "\nStopped"

    def _record(self):
        while self.isrecording:
            print "Downloading tweets"

main = tk.Tk()
app = App(main)
main.mainloop()

I am trying to apply this to my code, the Start button works properly and does everything that it is supposed to do, but the Stop button does not do anything. The window does not freeze or anything, its just that the stop button has no effect. The stream continues as nothing had happened. Here I post my code:

from Tkinter import *
import threading
import codecs
import urllib, json, tweepy,time
from datetime import datetime
from tweepy import Stream
from tweepy import OAuthHandler
from tweepy.streaming import StreamListener

consumer_key = ""
consumer_secret = ""
access_key = ""
access_secret = ""
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
keyword = "Poland"

class App():
    def __init__(self, master):
        self.isrecording = False
        self.button1 = Button(main, text='start')
        self.button2 = Button(main, text='stop')
        self.button1.bind("<Button-1>", self.startrecording)
        self.button2.bind("<Button-1>", self.stoprecording)
        self.button1.pack()
        self.button2.pack()

    def startrecording(self,event):
        self.isrecording = True
        t = threading.Thread(target=self._record)
        t.start()

    def stoprecording(self, event):
        self.isrecording = False

    def _record(self):
        while self.isrecording:
            class listener(StreamListener):
                def on_data(self,data):
                    imageFolder = "H:\Bogdan\imageFolder"
                    decoded = json.loads(data)
                    encoded = decoded['text'].encode('ascii','ignore')
                    if "http" not in encoded:
                        encodedStrip = encoded.translate(None, '@,/,\\,",<,>,:,|,?,*').replace("\n","")
                        print encodedStrip
                        if "media" in decoded['entities']:
                            for value in decoded['extended_entities']['media']:
                                imageLink = value['media_url']
                                urllib.urlretrieve(imageLink, imageFolder+"\\"+encodedStrip+"_"+str(time.time())+".jpg")
                        print 'downloading...'
                        return True

                    else:
                        encodedHTTP = encoded[:encoded.index("http")-2]
                        encodedStrip = encodedHTTP.translate(None, '@,/,\\,",<,>,:,|,?,*').replace("\n","")
                        print encodedStrip
                        if "media" in decoded['entities']:
                            for value in decoded['extended_entities']['media']:
                                imageLink = value['media_url']
                                urllib.urlretrieve(imageLink, imageFolder+"\\"+encodedStrip+"_"+str(time.time())+".jpg")
                        print 'downloading...'
                        return True
                def on_error(self,status):
                    print status

            twitterStream = Stream(auth,listener())
            twitterStream.filter( track = [keyword] )



main = Tk()
app = App(main)
main.mainloop()

Any idea on what I have to change to get this working?

Thank you very much!

The problem I guess with your code is that, you initialised a stream object inside the while loop, You must understand that the Stream objects contains an infinite loop within itself, which continuously looks for new streaming tweets. So Once you initialise a Stream object, It will automatically run until you kill the process manually, so there is no point in initialising the Stream object under the while loop

The strategy you need to follow is:

  • Initialise the Stream object when the start button is pressed.
  • Stop the streaming when stop button is pressed.

This behaviour can be easily achieved by editing your on_data() method, you may add the following lines in your on_data() method at the end where return True is being written:

if isrecording: #Initialise a variable named isrecording.
    return True
else:
    return False

I don't have much knowledge about tkinter but I can tell you the reason your "stop" button isn't working because you're not stopping the stream.

Within class listener(StreamListener): you need to specify twitterStream.disconnect() . What this will do is stop the connection between you and the Streaming API.

This can be added with:

while isrecording:
    ## enter code here
else:
    ## anything that might apply

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM