这是我的代码,因为我平时 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 = recr1.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 左右,随后越来越大
另外想问下如果只是用于识别包装盒上的产品序列号(大写英文数字组成,位数固定,手机拍照的,白底黑字/黑底白字都有可能)有效果更好的方案吗?

查一下具体的内存是被什么东西占用了? 估计是模型被多次加载,但从来不释放?

ocr = PaddleOCR(use_angle_cls=True, lang='en')这个要是放 do_ocr 里面呢我之前看别人另一个识别的用的 cnocr.readthedocs.io/zh/latest/usage/

如果是这个要放进去的原因,为什么放外面反而会被多次加载?放外面不是更应该不会被多次加载么?

我的意思是既然感觉 PaddleOCR 有问题,就别维持它的全局对象了,没有引用看垃圾回收能不能收了它

可能是 ocr 对象维持了一些历史记录。你扫一次内存就占着不释放了。

如果对这个库不了解, 可以在子进程里初始化它, 子进程销毁的时候就清理了. 不过估计会慢... 优化的地方很多

但是每次 ocr 都加载一次模型感觉会很慢

/dev/shm/这个是在内存的,会不会文件没有删掉,滞留在内存了

我看 top 是 gunicorn 这个进程占的内存

不过你提醒我了 /dev/shm/ 确实堆了 10GB 的图没删掉,不知道为什么,不过影响不大

怎么会影响不大。。。这里应该用 with 自动管理

with 能实现代码块结束自动删除文件么

paddleocr 内存分配管理有问题是个很长时间的问题了。我印象官方 github 有几个 issues 就是讨论这个的,而且跨了多个版本,你可以去查一下。之前有说是因为框架缓存的原因,有人说不是。我之前遇到这个问题也是通过重启来解决,尝试读了一下 c++ 代码部分还是太复杂了,没有解决的精力和能力。

可以参考这个 标准库里面有 docs.python.org/zh-cn/3/library/tempfile.html

如#13 所言,paddle OCR 的内存占用是个老问题,可以看 issue github.com/PaddlePaddle/PaddleOCR/discussions/6977

也可以手动调用 try_shrink_memory 来释放内存

一定要用猴子吗,用 fastapi 呢

python 多进程会将全局环境复制到每个子进程flask 我不清楚要怎么做,最好使用 cache 而不是全局变量,然后每个子进程调用时从 cache 懒加载读取

我也是 Flask+paddleocr ,用的 CPU 版本,1G 内存,都是小图片,大概半年才会内存满了重启一次

可以尝试 paddleocr 转 onnx 用 PyTorch ,TF 或者 tensorrt 这种比较成熟的框架,尽量不要使用受众很小的这种框架,有 bug 都不一样会改