Найти - Пользователи
Полная версия: flask+uwsfi+nginx deployment error with picamera (raspberry pi)
Начало » Web » flask+uwsfi+nginx deployment error with picamera (raspberry pi)
1
mc-black
Здравствуйте! Flask-приложение получает картинку с камеры raspberry pi 4 через библиотеку picamera (встроен в raspberry os). На отладочном web-сервере Flask всё работает как ожидается - картинка выдается через шаблон, обновляется при повторных запросах. Под серверами uwsgi/nginx приложение работает, кроме отработки view-функции с камеры - нет ответа (response). Часть кода:

 # == smapp.py ==
from flask import Flask, send_file
from picamera import PiCamera
from io import BytesIO
app = Flask(__name__)
@app.route("/camera.jpg")
def camera_jpg():
    steam = BytesIO()
    camera = PiCamera()
    camera.resolution = (1024, 768)
    camera.capture(steam, 'jpeg')
    camera.close()
    steam.seek(0)
    resp = send_file(steam, mimetype='image/jpeg')
    resp.headers['Cache-Control'] = 'no-cache'
    return resp
Стоит отметить, что виртуальное окружение venv не создавал, все библиотеки установил глобально. Библиотеку picamera не трогал никак.

Сталкивался с похожей ситуацией, когда Flask-приложение управляло gpio портами. Решением стало добавить пользователя www-data в группу gpio - это работало под uwsgi/nginx (и не работало под wsgi/apache). Здесь пробовал добавлять www-data в группу video (в сети человеку это помогло с захватом видеопотока с камеры). Также добавлял сразу во много других групп, но результата это не дало. Какие идеи стоит попробовать? Каким путем мне погуглить тему ещё?

Настройки uwsgi
 #== wsgi.ini ==
[uwsgi]
module = wsgi:app
master = true
processes = 2
socket = smapp.sock
chmod-socket = 666
uid = www-data
gid = www-data
vacuum = true
die-on-term = true
plugins = python3

Сервис запуска uwsgi
 #== /etc/systemd/system/smapp.service ==
[Unit]
Description=uWSGI instance to serve smapp
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/html
ExecStart=/usr/bin/uwsgi --ini wsgi.ini
[Install]
WantedBy=multi-user.target


Настроки nginx
#== /etc/nginx/sites-available/smapp ==
server {
listen 80;

location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/html/smapp.sock;
}
}

В логах nginx и статусе uwsgi можно видеть отсылки на ошибку, возникающую в send_file, думаю из-за пустого потока по причине недостатка прав доступа к библиотеке picamera. Что я сделал не так?
py.user.next
mc-black
В логах nginx и статусе uwsgi можно видеть отсылки на ошибку, возникающую в send_file, думаю из-за пустого потока по причине недостатка прав доступа к библиотеке picamera.
Для начала убедись в этом. Не надо строить предположений. Закомментируй код, где steam заполняется данными от камеры и заполни его тестовыми данными вручную. После этого обратись уже к этому маршруту на сервере, он должен выдать твои тестовые данные. Так ты будешь точно знать, что send_file() не работает из-за пустоты в байтовом потоке, а не предполагать это.

После этого уже можно разбираться с камерой.
mc-black
Спасибо за совет, py.user.next! Вот как я поменял код:
 # smapp.py
@app.route("/camera.jpg")
@login_required
def camera_jpg():
    #steam = BytesIO()
    #camera = PiCamera()
    #camera.resolution = (1024, 768)
    #camera.capture(steam, 'jpeg')
    #camera.close()
    #steam.seek(0)
    #resp = send_file(steam, mimetype='image/jpeg')
    #resp.headers['Cache-Control'] = 'no-cache'
    #return resp
    filepath = os.path.join(basedir, 'test.jpg')
    with open(filepath, 'rb') as f:
        steam = BytesIO(f.read())
    steam.seek(0)
    resp = send_file(steam, mimetype='image/jpeg')
    resp.headers['Cache-Control'] = 'no-cache'
    return resp
В отладке на встроенном в Flask сервере работает - выдает файл, а через uwsgi - нет. Вот, что показывает статус сервиса uwsgi:
File "/usr/local/lib/python3.7/dist-packages/flask_login/utils.py", line 272, in decorated_view
return func(*args, **kwargs)
File "./smapp.py", line 118, in camera_jpg
resp = send_file(steam, mimetype='image/jpeg')
File "/usr/lib/python3/dist-packages/flask/helpers.py", line 592, in send_file
data = wrap_file(request.environ, file)
File "/usr/lib/python3/dist-packages/werkzeug/wsgi.py", line 893, in wrap_file
return environ.get('wsgi.file_wrapper', FileWrapper)(file, buffer_size)
SystemError: <built-in function uwsgi_sendfile> returned a result with an error set
mc-black
Нашел решение в сети.
j0hnsmith
Just got this with Python 3.6.1 and flask send_file(), running uwsgi 2.0.15 with –wsgi-disable-file-wrapper makes the problem go away.

Отключил file-wrapper uwsgi в файле настроек:
#wsgi.ini
wsgi-disable-file-wrapper = true

Спасибо за наводки!!!
py.user.next
mc-black
Вот как я поменял код
Можно было просто вот так сделать
  
>>> import io
>>> 
>>> stream = io.BytesIO(b'abcd')
>>> stream.read()
b'abcd'
>>>
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB