views:

138

answers:

1

Update:

I switched this back from answered as I tried the solution posed in cogent Nick's answer and switched to Google's urlfetch:

logging.debug("starting urlfetch for http://%s%s" % (self.host, self.url))
result = urlfetch.fetch("http://%s%s" % (self.host, self.url), payload=self.body, method="POST", headers=self.headers, allow_truncated=True, deadline=5)
logging.debug("finished urlfetch")

but unfortunately finished urlfetch is never printed - I see the timeout happen in the logs (it returns 200 after 5 seconds), but execution doesn't seem tor return.


Hi All-

I'm attempting to play around with Twitter's Streaming (aka firehose) API with Google App Engine (I'm aware this probably isn't a great long term play as you can't keep the connection perpetually open with GAE), but so far I haven't had any luck getting my program to actually parse the results returned by Twitter.

Some code:

logging.debug("firing up urllib2")
req = urllib2.Request(url="http://%s%s" % (self.host, self.url), data=self.body, headers=self.headers)
logging.debug("called urlopen for %s %s, about to call urlopen" % (self.host, self.url))
fobj = urllib2.urlopen(req)
logging.debug("called urlopen")

When this executes, unfortunately, my debug output never shows the called urlopen line printed. I suspect what's happening is that Twitter keeps the connection open and urllib2 doesn't return because the server doesn't terminate the connection.

Wireshark shows the request being sent properly and a response returned with results.

I tried adding Connection: close to my request header, but that didn't yield a successful result.

Any ideas on how to get this to work?

thanks

-Simon

+1  A: 

urllib on App Engine is a thin wrapper around the urlfetch API. You're right about what's happening: Twitter's streaming API never terminates its response, so it times out, and urlfetch throws an exception.

If you use urlfetch directly, you can set the timeout (up to 10 seconds), and set allow_truncated to True so you can get the partial result. The Twitter streaming API really isn't a good match for App Engine, though, because App Engine requests are limited to 30 seconds of execution time, and urlfetch requests can't send back results progressively, or take more than 10 seconds. Using Twitter's 'standard' API would be a better option.

Nick Johnson
Thanks - that's a great explanation for what's happening.Re: 'standard' API, I assume you mean something like the http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses-public_timeline - but there is no great analog to the filtering capability of the stream, is there?
Simon
It depends on how you want to filter. The standard 'search' API does most of that. Another alternative would be to deploy a service elsewhere that uses the streaming API, and packages up batches to be sent to your app via HTTP. I've actually written a small tool to do just that, if you're interested.
Nick Johnson
I would definitely be interested in such a tool if you're up for sharing!
Simon
Here it is, such as it is: http://github.com/Arachnid/whofoundit/blob/master/feeder.py . It's not very polished, but the basic workflow is clear: It uses a producer/consumer pattern to fetch entries from Twitter and add them to a queue. Dropped connections are automatically retried. The consumer fetches batches from the queue and uploads them to any HTTP endpoint, with a batch every n results or m seconds (whichever comes first).
Nick Johnson