greenlet错误:无法切换到不同的线程。

9

我有一个 Flask 应用程序,在尝试将 Flask 与 faust 集成时遇到了以下错误。

app.py

import mode.loop.eventlet
import logging
import logging.config
import json
from flask import Flask
from elasticapm.contrib.flask import ElasticAPM

def create_app():
    app = Flask(__name__)
    configure_apm(app)
    configure_logging()
    register_blueprints(app)
    register_commands(app)
    return app

main.py

from flask import jsonify
from litmus.app import create_app
from intercepter import Intercepter

app = create_app()
app.wsgi_app = Intercepter(app.wsgi_app , app)

@app.route('/status')
def status():
    return jsonify({'status': 'online'}), 200

另一个控制器

@api_blue_print.route('/v1/analyse', methods=['POST'])
def analyse():
    analyse_with_historic_data.send(value=[somedata])
    return jsonify({'message': 'Enqueued'}), 201

analyse_with_historic_data.py

@app.agent(analysis_topic)
async def analyse_with_historic_data(self, stream):
    async for op in stream:
        entity_log = EntityLog.where('id', op.entity_log_id).first()

错误追踪:

Traceback (most recent call last):
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 461, in fire_timers
    timer()
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/timer.py", line 59, in __call__
    cb(*args, **kw)
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/semaphore.py", line 147, in _do_acquire
    waiter.switch()
greenlet.error: cannot switch to a different thread
Traceback (most recent call last):
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 461, in fire_timers
    timer()
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/timer.py", line 59, in __call__
    cb(*args, **kw)
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/semaphore.py", line 147, in _do_acquire
    waiter.switch()
greenlet.error: cannot switch to a different thread
Traceback (most recent call last):
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/queue.py", line 118, in switch
    self.greenlet.switch(value)
greenlet.error: cannot switch to a different thread
^CError in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/threading.py", line 551, in wait
    signaled = self._cond.wait(timeout)
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/threading.py", line 299, in wait
    gotit = waiter.acquire(True, timeout)
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/semaphore.py", line 107, in acquire
    hubs.get_hub().switch()
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 298, in switch
    return self.greenlet.switch()
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 350, in run
    self.wait(sleep_time)
  File "/Users/sahilpaudel/.pyenv/versions/3.6.5/lib/python3.6/site-packages/eventlet/hubs/kqueue.py", line 96, in wait
    time.sleep(seconds)

我一直在尝试使用monkey.patch_all来解决这个问题,但它也无法正常工作,并给出了另一个堆栈跟踪,指出锁定无法释放。
2个回答

14

我曾尝试使用Pycharm调试flask应用时遇到了类似的问题。

最终,我解决了问题,方法是在Pycharm中启用gevent兼容性:
文件 -> 设置 -> 构建、执行、部署 -> Python调试器 -> Gevent兼容


6
在 VSCode 中,您可以通过在 launch.json 文件中添加 "gevent": true 来实现相同的操作。有关详细信息,请参见此处 的文档。 - Alex Telon
非常感谢 @AlexTelon。我已经寻找了一段时间关于那个问题的答案,但是你的解决方案是最简单的。 - Ariel Catala Valencia
@alex-telon,看起来TS正在使用eventlet。你确定"gevent": true是正确的配置吗?但它确实可以在我使用eventlet时正常工作。 - Kuznetsov-M
@Kuznetsov-M 我不确定。但如果我没记错的话,我也是在使用 eventlet 而不是 gevent。而这里的 OP 使用了 greenlet。我猜这些工具以类似的方式工作,这就是为什么这个标志对我也起作用的原因。 - Alex Telon
我曾经遇到类似的问题,这解决了我的问题,但现在我无法正常调试我的 Python 代码。 - mishadr

1

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - xlmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接