这是我的代码,因为我平时 python 写得少,不熟练,如果代码质量差请别喷
import json, re
import uuid
from urllib.parse import quote, unquote
import yaml
import os, urllib.request
import time
from flask import Flask, config, render_template, request, redirect, make_response
from paddleocr import PaddleOCR, draw_ocr
ocr = PaddleOCR(use_angle_cls=True, lang='en')
app = Flask(__name__)
@app.route('/ocr', methods=['GET'])
def do_ocr():
if request.method == 'GET':
data = request.args
if 'url' in data:
url = unquote(data['url'])
else:
return ""
tmp_path = f"/dev/shm/{uuid.uuid4()}"
urllib.request.urlretrieve(url, tmp_path)
result = ocr.ocr(tmp_path, cls=True)
data = ""
for recr in result:
rec = recr[1][0].upper()
data += rec + ","
os.remove(tmp_path)
return data.strip(",")
if __name__ == '__main__':
app.run()
ocrapi.py 是从别处复制来的猴子补丁(不然好像并发会有问题)
from gevent import monkey, pywsgi
monkey.patch_all()
from app import app
用了 supervisor 启动:
[program:ocrapi]
command=gunicorn --workers 6 --worker-class=gevent --worker-connections=50 -b 0.0.0.0:8080 ocrapi:app
directory=/opt/ocrapi/
user=root
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/ocrapi.log
loglevel=info
服务启动时内存占用在 2GB 左右,随后越来越大
另外想问下如果只是用于识别包装盒上的产品序列号(大写英文数字组成,位数固定,手机拍照的,白底黑字/黑底白字都有可能)有效果更好的方案吗?
1
ggvm 260 天前
查一下具体的内存是被什么东西占用了?
估计是模型被多次加载,但从来不释放? |
2
Puteulanus 260 天前
ocr = PaddleOCR(use_angle_cls=True, lang='en')
这个要是放 do_ocr 里面呢 我之前看别人另一个识别的用的 https://cnocr.readthedocs.io/zh/latest/usage/ |
3
drymonfidelia OP @Puteulanus 如果是这个要放进去的原因,为什么放外面反而会被多次加载?放外面不是更应该不会被多次加载么?
|
4
Puteulanus 260 天前
@drymonfidelia 我的意思是既然感觉 PaddleOCR 有问题,就别维持它的全局对象了,没有引用看垃圾回收能不能收了它
|
5
est 260 天前
@drymonfidelia 可能是 ocr 对象维持了一些历史记录。你扫一次内存就占着不释放了。
|
6
ClericPy 260 天前
如果对这个库不了解, 可以在子进程里初始化它, 子进程销毁的时候就清理了. 不过估计会慢... 优化的地方很多
|
7
drymonfidelia OP @Puteulanus 但是每次 ocr 都加载一次模型感觉会很慢
|
8
kaneg 259 天前 via iPhone
/dev/shm/这个是在内存的,会不会文件没有删掉,滞留在内存了
|
9
drymonfidelia OP @kaneg 我看 top 是 gunicorn 这个进程占的内存
|
10
drymonfidelia OP @kaneg 不过你提醒我了 /dev/shm/ 确实堆了 10GB 的图没删掉,不知道为什么,不过影响不大
|
11
infun 259 天前
@drymonfidelia 怎么会影响不大。。。这里应该用 with 自动管理
|
12
drymonfidelia OP @infun with 能实现代码块结束自动删除文件么
|
13
kuanat 259 天前
paddleocr 内存分配管理有问题是个很长时间的问题了。我印象官方 github 有几个 issues 就是讨论这个的,而且跨了多个版本,你可以去查一下。
之前有说是因为框架缓存的原因,有人说不是。我之前遇到这个问题也是通过重启来解决,尝试读了一下 c++ 代码部分还是太复杂了,没有解决的精力和能力。 |
14
infun 259 天前
|
15
bringyou 259 天前
如#13 所言,paddle OCR 的内存占用是个老问题,可以看 issue
https://github.com/PaddlePaddle/PaddleOCR/discussions/6977 |
16
bringyou 259 天前
也可以手动调用 try_shrink_memory 来释放内存
|
17
ON9 259 天前 via Android
一定要用猴子吗,用 fastapi 呢
|
18
NoOneNoBody 259 天前
python 多进程会将全局环境复制到每个子进程
flask 我不清楚要怎么做,最好使用 cache 而不是全局变量,然后每个子进程调用时从 cache 懒加载读取 |
19
Eished 259 天前
我也是 Flask+paddleocr ,用的 CPU 版本,1G 内存,都是小图片,大概半年才会内存满了重启一次
|
20
founddev 259 天前
可以尝试 paddleocr 转 onnx 用 PyTorch ,TF 或者 tensorrt 这种比较成熟的框架,尽量不要使用受众很小的这种框架,有 bug 都不一样会改
|
21
clemente 258 天前
不要用 paddle 百度都快放弃了
|
22
CHchenkeyi 257 天前
至少代码没看出来由啥问题
|
23
CHchenkeyi 257 天前
做了很多飞桨的,基本上有问题就是 版本问题,要么更新 paddle 版本,要么更新 ocr 版本。很玄学
|
24
drymonfidelia OP @CHchenkeyi 更新了最新版更离谱了,运行半分钟 100%用完内存
|
25
so1n 157 天前
遇到内存溢出问题,都是用 gunicorn 的 max_requests
|
26
yinmin 156 天前
@drymonfidelia 25 楼是正解。gunicorn 加参数 --max-requests 1000 试试
(每个 worker 接收到 1000 次请求后就重启一个新的) 你自己测试一下 max-requests 用 500 、1000 、5000 、10000 哪个更优化。 |
27
mMartin 156 天前
把 OCR 单独封装个单例试试 paddleOCR 我至少在十个生产环境用 还真没遇到内存泄露
|
28
mMartin 156 天前
要么就把 OCR 单独封装一个服务 RPC 调用 我检测分割分类和 OCR 经常一起用
|