17

I'm trying to figure out how to properly close an asynchronous tweepy stream.

The tweepy streaming module can be found here.

I start the stream like this:

stream = Stream(auth, listener)
stream.filter(track=['keyword'], async=True)

When closing the application, I try to close the stream as simple as:

stream.disconnect()

This method seems to work as intended but it seems to have one problem: the stream thread is still in the middle of the loop (waiting/handling tweets) and is not killed until the next loop, so when the stream receives a tweet even after the app has closed, it still tries to call the listener object (this can be seen with a simple print syntax on the listener object). I'm not sure if this is a bad thing or if it can simply be ignored.

I have 2 questions:

  1. Is this the best way to close the stream or should I take a different approach?
  2. Shouldn't the async thread be created as a daemon thread?
Wilco
  • 928
  • 3
  • 9
  • 20

4 Answers4

3

I had the same problem. I fixed it with restarting the script. Tweepy Stream doesn't stop until the next incoming tweet.

Example:

import sys
import os

python=sys.executable

time.sleep(10)

print "restart"
os.execl(python,python,*sys.argv)

I didn't find another solution.

Burkay
  • 91
  • 1
  • 1
  • 11
2

I am not positive that it applies to your situation, but in general you can have applicable entities clean up after themselves by putting them in a with block:

with stream = Stream(auth, listener):
    stream.filter(track=['keyword'], async=True)
    # ...
# Outside the with-block; stream is automatically disposed of.

What "disposed of" actually means, it that the entities __exit__ function is called.
Presumably tweepy will have overridden that to Do The Right Thing.
As @VooDooNOFX suggests, you can check the source to be sure.

Edward
  • 1,000
  • 5
  • 16
0

This is by design. Looking at the source, you will notice that disconnect has no immediate termination option.

def disconnect(self):
    if self.running is False:
        return
    self.running = False

When calling disconnect(), it simply sets self.running = False, which is then checked on the next loop of the _run method

You can ignore this side effect.

VooDooNOFX
  • 4,674
  • 2
  • 23
  • 22
0

Instead of restarting the script, as @burkay suggests, I finally deleted the Stream object and started a new one. In my example, someone wants to add a new user to be followed, so I update the track list this way:

stream.disconnect() # that should wait until next tweet, so let's delete it
del stream
# now, create a new object
stream = tweepy.Stream( auth=api.auth, listener=listener )
stream.userstream( track=all_users(), async=True )
Enric Mieza
  • 342
  • 2
  • 10