环境是 Flask + Gunicorn + gevent
已经在入口函数打了 monkey patch
可是在别的文件调用 requests 方法还是会报无限递归错误
文件层级结构
- manage.py
- gunicorn_config.py
- function
-- handler.py
-- ...
-- packageA
---- api.py <- 此处调用 requests 方法 eg. get(), post()
gunicorn 配置
manage.py 开头已经打了 monkey patch
gunicorn 运行命令
gunicorn -c gunicorn_config.py manage.py
错误
版本
python3.6.9 gunicorn 20.0.4 gevent 1.4.0 docker images alpine (费了老半天才装上 gevent...)
先谢谢各位大佬
1
Ritter OP 大佬们都下班了吗 T T
|
2
Ritter OP |
3
cz5424 2020-03-12 19:59:28 +08:00 via iPhone
看不懂啥操作,猴子补丁跟你 requests 递归有什么关系?
|
4
wuwukai007 2020-03-12 20:57:32 +08:00 via Android
代码贴全一点
|
5
Qzier 2020-03-13 02:56:33 +08:00 via iPhone
把 flask 换成 starlette
|
6
Ritter OP @cz5424 不打猴子补丁也会报这个错误 但是我看网上说 gunicorn 使用 gevent 内部已经 patch 了 很奇怪
|
7
Ritter OP @wuwukai007 其他的没什么代码了就是在 api.py 文件调用了 requests 的 get,post 方法
|
9
Ritter OP github.com/gevent/gevent/issues/1531
这个 issues 跟我情况差不多 |
10
todd7zhang 2020-03-13 09:07:16 +08:00
|
11
todd7zhang 2020-03-13 09:08:31 +08:00
这里有说, 先 monkey.patch_all(), 你可以看看是不是 gunicorn_config.py 第一行的 from function.handler import app, db 这里面是不是有 import requests
|
12
Ritter OP @todd7zhang 已经试过先在 gunicorn_config 打 patch 还是一样会报错
|
13
ClericPy 2020-03-13 09:27:17 +08:00
呃, 提几个常识
1. 猴子补丁要加在所有文件最顶端引用, 看你这情况 config.py 明显是在 manage.py 的顶端, 所以不该在后者打, 而是在前者那里打 2. gunicorn 借用 gevent 提速来优化 socket io 的时候, 连 workers 也要换的, 具体操作一般是 gunicorn -k gevent, 也就是你在 config.py 里的 worker class 那个参数, 所以就像第一点说的, 这个文件顶部才需要打, 不需要在 manage 里显性再 patch all 一次. 所以我一般 gunicorn handle flask 的时候, 是单独开一个符合 wsgi 的 py 文件, 里面产生一个 app, 而不是用 flask 自带生成的 manage.py 来操作 PS: 实际看你的报错, 最常见于违反相互引用的问题 (昨天刚写出来一个这种错误, 虽然大部分情况下 python 做过优化来防止多次引用, 但相互依赖还是违反常识的会递归报错), 比如 A 模块里的 a 在初始化的时候依赖 B 模块的 b 的初始化, 恰恰 B 在初始化的时候又依赖了 A 里 a 的初始化, 也就产生了死锁无限递归去初始化 |
14
Ritter OP @ClericPy 已经试过在 config 前打了还是会报错 我看了 gunicorn 内部使用 gevent 的时候也已经 patch 了 所以我觉得应该不需要打了吧 可以顺便请教一下你是怎么单独开一个符合 wsgi 的 py 文件运行 gunicorn 的吗 谢谢
|
15
ClericPy 2020-03-13 09:50:39 +08:00
@Ritter #14 实际上就是搞一个空文件把创建 app 对象的过程单独抛出来, 网上到处都是...
``` manage 因为我六七年没用 flask 命令行去初始化也不知道里面经历的什么... 看你上面图片 config 开头就引用 app 就是个典型错误, 因为补丁要打在所有操作之前, 而 config 的第一个操作不像打补丁而是 去 handler 里 import 东西, 所以这个错误不知道你后面修了没有 ``` 我回复里点 py 居然报了一大堆 请不要在每一个回复中都包括外链,这看起来像是在 spamming 这论坛也不能贴代码... |
16
ClericPy 2020-03-13 09:53:12 +08:00
在 docker 里调试如果费劲, 可以用最短案例先复现一个必定发生的代码吧, 那样举例子不会暴露源码也能更清晰地找问题...
又重新看了下你报错, 我好像误解了, 实际错误应该是 gevent 在 3.6 上给 ssl 打补丁的那个常见错误 |
18
ClericPy 2020-03-13 12:48:02 +08:00
@Ritter #17 是啊, 就是 patch 位置不对, 一定要在第一行要执行的代码里打, 用多了就习惯了, 三四年没碰过 gevent 了...
|
19
triangle111 2020-03-13 16:21:29 +08:00
import gevent.monkey
gevent.monkey.patch_all() # 服务地址( adderes:port ) bind = '127.0.0.1:5002' # 启动进程数量 workers = 2 worker_class = 'gevent' threads = 20 preload_app = True reload = True x_forwarded_for_header = 'X_FORWARDED-FOR' chdir = './' proc_name='gunicorn.pid' #记录 PID pidfile='debug.log' access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' #设置 gunicorn 访问日志格式,错误日志无法设置 errorlog = "./errlog" accesslog = "./logs" 贴一下自己 |