0

I'm building a flask app that displays real-time data visualizations of tweets based on a user input. Right now, the client is still hosted locally and I'm just trying to get to the point where a json of a single tweet gets emitted from the server to the client. This is also my first time building a flask app on my own, so I've been learning HTML/CSS/node.js/JS along the way (be gentle with me).

My problem is with the backend/server. Here is the relevant flask code:

from flask import Flask, request, render_template, session
from flask_socketio import SocketIO, emit
from time import sleep
import threading
from threading import Thread, Event, Lock
import eventlet
import json
import TweePoll_API_nostream

eventlet.monkey_patch(socket=True)
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socket = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)
streamer2 = TweePoll_API_nostream.getTweet()
thread = None
thread_lock = Lock()

def background_thread():
    count = 0
    while True:
        socket.sleep(10)
        x = streamer2.main(v)
        count += 1
        socket.emit('my_response',
            {'data': x, 'count': count},
            namespace='/output')

@app.route('/', methods = ['GET','POST'])
def index():
    return(render_template("index.html", async_mode = socket.async_mode))

@socket.on('my_event', namespace='/output')
def test_message(message):
    global v
    v = message['data']
    print(v)
    global thread 
    with thread_lock:
        if thread is None:
            thread = socket.start_background_task(background_thread)
    emit('my_response', {'data': v, 'count': 0})

if __name__ == '__main__':
    socket.run(app, port = 5000, debug = True)

The error occurs on x = streamer2.main(v) in the background_thread() function. Here is the relevant code for the tweepy streamer:

import tweepy
import config
import TweePoll_NLP_single
import json

MLObj = TweePoll_NLP_single.ReadyForSQL()

class getTweet(object):
    def __init__(self):
        self.auth = tweepy.auth.OAuthHandler(config.ckey, config.csecret)
        self.auth.set_access_token(config.atoken, config.asecret)
        self.api = tweepy.API(self.auth)

    def main(self, keywrd):
        tweet = str()
        user = str()
        time = str()
        status = self.api.search(q = [keywrd + " @realDonaldTrump", keywrd + " @JoeBiden"], count = 1, result_type = "recent", lang = 'en')[0]

        if hasattr(status, "retweeted_status"):  # Check if Retweet
            try:
                tweet = status.retweeted_status.extended_tweet["full_text"]
            except AttributeError:
                tweet = status.retweeted_status.text
        else:
            try:
                tweet = status.extended_tweet["full_text"]
            except AttributeError:
                tweet = status.text

        user = status.author.screen_name
        time = str(status.created_at)
        prez = MLObj.whichPrez(tweet)
        clean = MLObj.kleenex(tweet)
        NRCemo = MLObj.NRCEmo(clean)

        printDF = json.dumps({"tweet":tweet, "clean":clean,
            "prez":prez, "NRCEmo":NRCemo, "time":time, "username":user})

        return(printDF)

This code isn't reproducible, because it connects to another file for the NLP/sentiment tagging, plus the frontend isn't included. Let me know if I need to send a link to my github or something to fix this.

Here is the error output:

Exception in thread Thread-6:
Traceback (most recent call last):
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\tweepy\binder.py", line 183, in execute
    resp = self.session.request(self.method,
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\adapters.py", line 439, in send
    resp = conn.urlopen(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 976, in _validate_conn
    conn.connect()
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connection.py", line 342, in connect
    self.ssl_context = create_urllib3_context(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\util\ssl_.py", line 276, in create_urllib3_context
    context.options |= options
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 481 more times]
RecursionError: maximum recursion depth exceeded

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\swagj\Documents\GitHub\TweePoll\TweePoll_Server_V2.py", line 28, in background_thread
    x = streamer2.main(v)
  File "C:\Users\swagj\Documents\GitHub\TweePoll\TweePoll_API_nostream.py", line 21, in main
    status = self.api.search(q = [keywrd + " @realDonaldTrump", keywrd + " @JoeBiden"], count = 1, result_type = "recent", lang = 'en')[0]
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\tweepy\binder.py", line 250, in _call
    return method.execute()
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\tweepy\binder.py", line 191, in execute
    six.reraise(TweepError, TweepError('Failed to send request: %s' % e), sys.exc_info()[2])
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\six.py", line 702, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\tweepy\binder.py", line 183, in execute
    resp = self.session.request(self.method,
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\sessions.py", line 530, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\requests\adapters.py", line 439, in send
    resp = conn.urlopen(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 670, in urlopen
    httplib_response = self._make_request(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connectionpool.py", line 976, in _validate_conn
    conn.connect()
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\connection.py", line 342, in connect
    self.ssl_context = create_urllib3_context(
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\site-packages\urllib3\util\ssl_.py", line 276, in create_urllib3_context
    context.options |= options
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "C:\Users\swagj\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 481 more times]
tweepy.error.TweepError: Failed to send request: maximum recursion depth exceeded

Final dump, here is my info:

Windows 10
python = 3.8.3
eventlet = 0.25.2
tweepy = 3.8.0
websocket-client = 0.57.0
websockets = 8.1
Flask = 1.1.2
Flask-SocketIO = 4.3.0

I have no idea why this doesn't work, but I have a feeling it has to do with eventlet. Any clues? Happy to give more info if needed :)

lemonlin
  • 96
  • 6
  • 1
    I googled the repeated line (`super(SSLContext, SSLContext).options.__set__(self, value)`) and found this: https://stackoverflow.com/questions/49820173/requests-recursionerror-maximum-recursion-depth-exceeded is it relevant? – Kevin Wang Jul 22 '20 at 03:38
  • @KevinWang when I looked up the error I saw some similar stuff (not that specific one), but the big difference is that their problem is with gevent and I don't have that/I'm definitely running on eventlet. I do use a similar approach as in that SO when I monkeypatch eventlet, but it hasn't helped. – lemonlin Jul 22 '20 at 03:44
  • ah yeah sorry, I could have noticed that if I looked at your code first. Perhaps [this](https://github.com/gevent/gevent/issues/1016) will fix your problem: "The problem is that you're importing requests before you monkey patch. You must monkey patch before importing anything else." – Kevin Wang Jul 22 '20 at 03:47
  • 2
    more reference: https://eventlet.net/doc/patching.html#monkeypatching-the-standard-library "It is important to call monkey_patch() as early in the lifetime of the application as possible..." – Kevin Wang Jul 22 '20 at 03:48
  • Well good news and bad news, placing eventlet/monkeypatch at the top did fix the recursion error, but my new error I saw in passing while researching this: `tweepy.error.TweepError: Failed to send request: wrap_socket() got an unexpected keyword argument '_context'`. I can edit the post with the full error output if you need it. Thank you so much for you help so far BTW! This is a lot more productive than running it over and over expecting a different result hahaha – lemonlin Jul 22 '20 at 03:52
  • from googling that error it looks like it's just an error in the imported libraries. Looks like it's been fixed in the source repository, so you can probably build from source (`install latest development version` at https://github.com/eventlet/eventlet#getting-eventlet) to resolve? – Kevin Wang Jul 22 '20 at 04:06
  • That worked! Thank you so so much! – lemonlin Jul 22 '20 at 04:13
  • Got the same issue, It was resolved by installing eventlet pip install -U eventlet – PKD Mar 24 '22 at 06:24

1 Answers1

0

For anyone else stumbling upon this... I was getting this error on a Flask app using eventlet (running Python 3.9):

File "/usr/lib/python3.9/ssl.py", line 603, in options super(SSLContext, SSLContext).options.set(self, value) File "/usr/lib/python3.9/ssl.py", line 603, in options super(SSLContext, SSLContext).options.set(self, value) File "/usr/lib/python3.9/ssl.py", line 603, in options super(SSLContext, SSLContext).options.set(self, value) [Previous line repeated 490 more times] RecursionError: maximum recursion depth exceeded

To make a long story short:

  • disabling eventlet.monkey_patch() corrected the issue in tests, but I wanted to keep it.
  • updating eventlet and dnspython fixed it for good for me.

Before:

dnspython==1.16.0
eventlet==0.30.2

After:

dnspython==2.3.0
eventlet==0.33.3
Fabien Snauwaert
  • 4,995
  • 5
  • 52
  • 70