Форум сайта python.su
Здравствуйте! 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
#== 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
#== /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
#== /etc/nginx/sites-available/smapp ==
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/html/smapp.sock;
}
}
Отредактировано mc-black (Окт. 8, 2021 23:20:27)
Офлайн
mc-blackДля начала убедись в этом. Не надо строить предположений. Закомментируй код, где steam заполняется данными от камеры и заполни его тестовыми данными вручную. После этого обратись уже к этому маршруту на сервере, он должен выдать твои тестовые данные. Так ты будешь точно знать, что send_file() не работает из-за пустоты в байтовом потоке, а не предполагать это.
В логах nginx и статусе uwsgi можно видеть отсылки на ошибку, возникающую в send_file, думаю из-за пустого потока по причине недостатка прав доступа к библиотеке picamera.
Отредактировано py.user.next (Окт. 9, 2021 00:52:23)
Офлайн
Спасибо за совет, 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
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
Офлайн
Нашел решение в сети.
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.
#wsgi.ini
wsgi-disable-file-wrapper = true
Офлайн
mc-blackМожно было просто вот так сделать
Вот как я поменял код
>>> import io >>> >>> stream = io.BytesIO(b'abcd') >>> stream.read() b'abcd' >>>
Офлайн