Werkzeug: Werkzeug вылетает после записи в закрытую трубу

Созданный на 20 июн. 2016  ·  41Комментарии  ·  Источник: pallets/werkzeug

У меня есть сервер Werkzeug, работающий за NGINX. Когда клиент отключается, ожидая ответа сервера Werkzeug, NGINX закрывает канал к Werkzeug. Когда программа python записывает ответ в Werkzeug, возникает следующее исключение и Werkzeug аварийно завершает работу:

Отслеживание (последний вызов последний):
Файл "server.py", строка 81, в
app.run (host = args.host, port = args.port, debug = False)
Файл "/usr/local/lib/python2.7/dist-packages/flask/app.py", строка 843, выполняется
run_simple (хост, порт, сам, ** параметры)
Файл "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", строка 694, в run_simple
внутренний()
Файл "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", строка 659, во внутреннем
srv.serve_forever ()
Файл "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", строка 499, в serve_forever
HTTPServer.serve_forever (сам)
Файл "/usr/lib/python2.7/SocketServer.py", строка 238, в serve_forever
self._handle_request_noblock ()
Файл "/usr/lib/python2.7/SocketServer.py", строка 297, в _handle_request_noblock
self.handle_error (запрос, client_address)
Файл "/usr/lib/python2.7/SocketServer.py", строка 295, в _handle_request_noblock
self.process_request (запрос, client_address)
Файл "/usr/lib/python2.7/SocketServer.py", строка 321, в process_request
self.finish_request (запрос, client_address)
Файл "/usr/lib/python2.7/SocketServer.py", строка 334, в finish_request
self.RequestHandlerClass (запрос, client_address, self)
Файл "/usr/lib/python2.7/SocketServer.py", строка 651, в init
self.finish ()
Файл "/usr/lib/python2.7/SocketServer.py", строка 710, в завершении
self.wfile.close ()
Файл "/usr/lib/python2.7/socket.py", строка 279, закрыт
self.flush ()
Файл "/usr/lib/python2.7/socket.py", строка 303, запущен.
self._sock.sendall (просмотр [write_offset: write_offset + buffer_size])
socket.error: [Errno 32] Сломанная труба

Есть ли какой-то параметр конфигурации, который мне не хватает, чтобы предотвратить сбой? Обычно перехватываются все исключения и возвращается ошибка 500, при этом сервер остается в рабочем состоянии.

Самый полезный комментарий

Руководствуясь недавней фиксацией исправления, я смог решить эту проблему, вызвав app.run с passthrough_errors = False. YMMV

Все 41 Комментарий

Используйте производственный сервер WSGI, такой как Gunicorn или uWSGI, а не сервер разработчика Werkzeug.

У меня очень похожая проблема, за исключением того, что я использую сервер разработчика Werkzeug для разработки (то есть AFAICT, его предполагаемое использование), то есть с браузером, напрямую подключенным к порту 5000.

Ошибка возникает несколько раз в час, вынуждая перезапуск сервера вручную для продолжения развития.

Вот обратная связь:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 659, in inner
    srv.serve_forever()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 499, in serve_forever
    HTTPServer.serve_forever(self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 238, in serve_forever
    self._handle_request_noblock()
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 297, in _handle_request_noblock
    self.handle_error(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 655, in __init__
    self.handle()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 216, in handle
    rv = BaseHTTPRequestHandler.handle(self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 251, in handle_one_request
    return self.run_wsgi()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi
    execute(self.server.app)
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 186, in execute
    write(b'')
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 152, in write
    self.send_header(key, value)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 401, in send_header
    self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe

У меня та же проблема, что и у @sfermigier с сервером разработки ( debug=True ), и такая же ошибка трассировки.

Такое поведение обычно происходит в очень простом случае: вы используете какие-то функции автозаполнения. Браузер запускает соединение для токенов запроса, а затем останавливается и запускает другой запрос для дополнительных токенов. В итоге вы получите много сломанных труб. И это не было проблемой до последней версии, которая полностью заблокировала сервер разработки.
Итак, предложение использовать полнофункциональный сервер приложений - хороший обходной путь, но я все еще вижу здесь проблему. Проблема, конечно, только в разработке, но тот факт, что она так часто срабатывает, беспокоит многих разработчиков, которые не привыкли к _протокольному внутреннему устройству_.
Сломанный канал - очень распространенное явление (подумайте о длинном запросе по ошибке и о том, что разработчик нажимает кнопку остановки браузера), и он не должен нарушать работу сервера разработки.
Только мое мнение. :)

@xcash

Такое поведение обычно происходит в очень простом случае: вы используете какие-то функции автозаполнения. Браузер запускает соединение для токенов запроса, а затем останавливается и запускает другой запрос для дополнительных токенов.

Если это связано, я могу подтвердить, что испытываю эту проблему, используя browsersync с gulp.js .

Есть ли у кого-нибудь решение, которое не включает запуск сервера WSGI? Кажется, я столкнулся с этой проблемой с ботами, выполняющими SYN-сканирование моего хоста.

@glennzw не могли бы вы

FWIW, я не очень внимательно следил за выпусками, и эта (очень раздражающая) проблема начала происходить для меня где-то в период с мая по август 2016 года, насколько я могу судить. Я добавил это в свой файл setup.py install_requires = ['Werkzeug<0.11', 'flask<0.11', ... который, похоже, помогает обойти проблему (IME, простое закрепление Werkzeug, похоже, не помогло?)

Для меня случай дублирования был достаточно простым - загрузить страницу, но не дать ей закончить загрузку. То есть просто вызовите _any_ ошибку сломанного канала - и веб-сервер выйдет из строя и не сможет обслуживать любые другие запросы. ИМХО, веб-серверы не могут обрушиться, когда клиент преждевременно закрывает соединение, даже если они находятся в стадии разработки.

Может быть, у всех вас где-то установлен passthrough_errors ?

@untitaker в этом случае, поддоны / колба № 1674 поддоны / колба № 1679 поддоны / колба № 1928, возможно, связаны?

Не знаю, мне бы хотелось, чтобы один из репортеров подтвердил.

26 августа 2016 г. 17:05:25 CEST Дэвид Лорд [email protected] написал:

@untitaker в этом случае поддоны / колба # 1674 поддоны / колба # 1679
поддоны / фляга №1928, возможно, связаны?

Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242761250

Отправлено с моего устройства Android с помощью K-9 Mail. Прошу прощения за краткость.

cc @miguelgrinberg

Я думаю, что Werkzeug должен обрабатывать поломку трубы и ошибки сброса соединения. Это действительно не показатель ошибки, клиент просто ушел. Похоже, в этом случае должно быть вызвано специальное исключение, которое распознается вышеупомянутым комплексным способом как исключение, которое следует игнорировать, даже если задана сквозная передача ошибок.

Вот как это делает Gunicorn: https://github.com/benoitc/gunicorn/blob/39f62ac66beaf83ceccefbfabd5e3af7735d2aff/gunicorn/workers/sync.py#L151 -L154

Вот что он должен делать. Я пытаюсь понять, как воспроизвести
это поведение, но пока нет четкого тестового примера. Отсюда вопрос
о passthrough_errors .

Я подозреваю, что это не ошибка Werkzeug, а браузер пользователя
просто остается открытым соединение, которое блокирует другие запросы (вместо
сбой сервера). Если вы закроете браузер и снова откроетесь, сервер должен
снова работать.

В пятницу, 26 августа 2016 г., в 11:54:16 -0700 Мигель Гринберг написал:

Я думаю, что Werkzeug должен обрабатывать поломку трубы и ошибки сброса соединения. Это действительно не показатель ошибки, клиент просто ушел. Похоже, в этом случае должно быть вызвано специальное исключение, которое распознается вышеупомянутым комплексным способом как исключение, которое следует игнорировать, даже если задана сквозная передача ошибок.

Вот как это делает Gunicorn: https://github.com/benoitc/gunicorn/blob/39f62ac66beaf83ceccefbfabd5e3af7735d2aff/gunicorn/workers/sync.py#L151 -L154

Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242821084

Да, и ошибки сломанной трубы _are_ отображаются, да, но они никогда не должны вешать сервер, как описано. См. Предыдущий комментарий о возможной причине.

Я снова проверил последние версии и все еще наблюдаю то же поведение в своей среде. Но поскольку у вас, похоже, возникли проблемы с воспроизведением, я попытался понять, почему я особенный.

import time
from flask import Flask
app = Flask(__name__)


@app.route('/')
def hello_world():
    time.sleep(5)
    return 'Hello, World!'


if __name__ == "__main__":
    app.run()

Он работает так, как ожидалось, с flask run но веб-сервер выйдет из строя, если вы закроете веб-браузер, прежде чем разрешить отображение ответа при запуске через python hello.py

Похоже, что часть вашего ответа потеряна.

В пятницу, 26 августа 2016 г., 12:29:39 -0700 Clayg написал:

Я снова проверил последние версии и все еще наблюдаю то же поведение в своей среде. Но поскольку у вас, похоже, возникли проблемы с воспроизведением, я попытался понять, почему я особенный.

You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment-242829536

да, в Slack triple-ticks вы блокируете цитату, а ctrl-return - как вы вводите новую строку
на github тройная галочка - это то, как вы блокируете цитату, но ctrl-return - это то, как вы отправляете
... в любом случае ... мышечная память

Я отредактировал свой пост сразу после его отправки, чтобы завершить его - и я отвечаю только потому, что похоже, что вы отвечаете по электронной почте, и я не уверен, что github отправит вам еще одно уведомление после моего редактирования.

Я не могу воспроизвести с помощью теста сна @clayg выше. На самом деле я вообще не получаю ошибку о сломанной трубе. Я закрываю браузер до того, как этот запрос вернет ответ, но Werkzeug все равно выполняет запрос до конца, он выводит строку журнала 200 на консоль и не показывает никаких ошибок.

Я также попробовал тот же трюк, используя мой пример потоковой передачи видео из фляги, в котором используется потоковый ответ для предоставления видеокадров в бесконечном потоке, и даже для этого я могу закрыть браузер, и запрос завершится без каких-либо ошибок. Это странно, потому что я уверен, что в прошлом это приложение вызывало ошибку сломанного канала на консоли перед завершением запроса.

На самом деле, я заговорил слишком рано. Я могу воспроизводить каждый раз с помощью своего приложения для потоковой передачи видео при использовании Python 2.7. Не могу воспроизвести на 3.5. Все трассировки стека выше относятся к 2.7, так что имейте это в виду, если вы тестируете Python 3.

Еще один интересный факт. При работе с перезагрузчиком, когда дочерний процесс завершается, главный процесс, запускающий перезагрузчик, запускает другой, поэтому прерывания не происходит. Но если вы запускаете сервер без перезагрузчика, ошибка сломанной трубы вернет вас в консоль.

Изменить: не обращайте внимания на перезагрузку, запускающую другую часть процесса, которая, похоже, не происходит, и вместо этого я, вероятно, видел эффект изменения настройки ошибки сквозной передачи.

Хорошо, вот анализ того, что, как мне кажется, происходит:

  • Клиент уходит в середине запроса
  • Запрос продолжается. Соединение сокета кажется буферизованным, поэтому в большинстве случаев запись в сокет не вызовет никаких проблем.
  • После завершения запроса класс сервера сокета выдаст на сокет сообщение flush() . Это было предметом старой ошибки в библиотеке Python, которая в настоящее время исправлена: http://bugs.python.org/issue14574. Решение в этом исправлении состояло в том, чтобы поймать socket.error и проигнорировать его.
  • Затем сервер сокетов пытается закрыть соединение. Это следующий кадр стека из трассировки OP:

File "/usr/lib/python2.7/SocketServer.py", line 710, in finish self.wfile.close()

  • К сожалению, в Python 2.7 первое, что делает метод socket.close() , - это снова сбрасывать:

File "/usr/lib/python2.7/socket.py", line 279, in close self.flush()

  • Эта вторая попытка сброса не защищена с помощью команды try / except, поэтому она вызывает исключение EPIPE.
  • Сервер сокетов перехватывает исключение и затем доставляет его в метод handle_error() сервера.
  • Реализация Werkzeug handle_error() смотрит на настройку passthrough_errors , и, поскольку она всегда установлена ​​на True , повторно вызывает ошибку EPIPE и позволяет ей пузыриться до Топ.

Код сокета на Python 3 совершенно другой, и, в частности, похоже, что он не имеет никаких вызовов сброса без try / exceptions вокруг них. Ошибка EPIPE даже не всплывает до Werkzeug при использовании Python 3.

У нас вообще есть passthrough_errors для true? В Werkzeug по умолчанию - false.

27 августа 2016 г., 02:10:13 CEST, Мигель Гринберг [email protected] написал:

Хорошо, вот анализ того, что, как мне кажется, происходит:

  • Клиент уходит в середине запроса
  • Запрос продолжается. Соединение сокета кажется
    буферизован, поэтому в большинстве случаев запись в сокет не вызывает никаких
    проблемы.
  • После завершения запроса класс сервера сокета выдаст flush()
    на розетке. Это было предметом старой ошибки в библиотеке Python.
    который в настоящее время исправлен: http://bugs.python.org/issue14574. В
    решение в этом исправлении заключалось в том, чтобы поймать socket.error и проигнорировать его.
  • Затем сервер сокетов пытается закрыть соединение. Это
    следующий кадр стека из трассировки OP:
 File "/usr/lib/python2.7/SocketServer.py", line 710, in finish
 self.wfile.close()

  • К сожалению, в Python 2.7 первым делом socket.close()
    метод снова сбрасывается:
 File "/usr/lib/python2.7/socket.py", line 279, in close
 self.flush()

  • Эта вторая попытка сброса не защищена с помощью try / except, поэтому
    это вызывает исключение EPIPE.
  • Сервер сокетов перехватывает исключение и затем доставляет его
    серверный метод handle_error() .
  • Реализация Werkzeug handle_error() смотрит на
    passthrough_errors setting, и поскольку мы всегда устанавливаем это значение
    True , повторно вызывает ошибку EPIPE и позволяет ей подняться вверх.

Код сокета на Python 3 совершенно другой, в частности,
похоже, что у него нет каких-либо вызовов сброса без try / excepts вокруг
их. Ошибка EPIPE даже не всплывает в Werkzeug при использовании
Python 3.

Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242881523

Отправлено с моего устройства Android с помощью K-9 Mail. Прошу прощения за краткость.

Ой, кхм: https://github.com/pallets/flask/pull/1679

Я думаю, что passthrough_errors должно зависеть от app.debug . NVM, бесполезен

На самом деле я не вижу другого выхода, кроме как отказаться от этого пиара. passthrough_errors=True просто делает то, что должен делать, что не является хорошим поведением по умолчанию, если к программе не подключен отладчик.

Неважно, я нашел другой способ. Два PR:

  • https://github.com/pallets/flask/pull/1996 - это решит проблему само по себе, за исключением того, что трассировка все еще видна
  • https://github.com/pallets/werkzeug/pull/998 - даже если passthrough_errors=True , никогда не вызывать ошибки сокета повторно. Я не думаю, что это когда-либо было намерением

Поскольку оба являются изменениями поведения в широком смысле, я бы предпочел не переносить их обратно.

Я думаю, что https://github.com/pallets/flask/pull/1996 - приемлемое решение. Важно то, что он исправляет общий случай, когда вы не хотите, чтобы исключения распространялись. Если вы действительно хотите распространить, то вы выполняете отладку, и в этом случае распространение socket.error, когда этого не должно быть, не имеет большого значения.

Однако исправление https://github.com/pallets/werkzeug/pull/998 не очень хорошее. Приложение может законно вызвать эти исключения из того, что оно делает с сокетами в своих собственных обработчиках, и они также будут отключены. Идеальным решением было бы, чтобы они перехватывались в том месте, где они возникают, а затем повторно вызывались как некоторый настраиваемый класс исключений, который handle_error может распознать и проигнорировать. Учитывая, что мы, вероятно, не хотим изменять или перегружать SocketServer , я думаю, что мой голос - просто оставить эту часть как есть. Вы получите сброс EPIPE на консоль, но только на Python 2, и, по крайней мере, он не остановит сервер после того, как будет внесено другое исправление. Это безвредно, и такое поведение существовало в прошлом, до того, как я сделал passthrough_errors сдача.

Однако описанное вами поведение происходит только при включенном PASSTHROUGH_ERRORS. В противном случае исключение перехватывается из Flask.

Думаю, это косметическое улучшение того не стоит.

27 августа 2016 г., 18:29:30 CEST, Мигель Гринберг [email protected] написал:

Я думаю, что https://github.com/pallets/flask/pull/1996 является приемлемым
решение. Важно то, что он исправляет общий случай, когда
вы не хотите, чтобы исключения распространялись. Если вы хотите размножаться,
то вы отлаживаете, и в этом случае вы получаете socket.error
размножается, когда этого не следует делать, не имеет большого значения.

Исправление https://github.com/pallets/werkzeug/pull/998 не очень хорошее
хотя. Приложение может вызвать эти исключения на законных основаниях из
что-то, что он делает с сокетами в своих собственных обработчиках, и они
тоже быть замолчать. Идеальным решением было бы поймать их
в том месте, где они возникают, а затем повторно возникают как некое настраиваемое исключение
класс, который handle_error может распознать и проигнорировать. Учитывая, что мы
вероятно, не хочу менять или перегружать SocketServer , я думаю, что мой
Голосование - просто оставить эту часть как есть. Вы получите EPIPE, сброшенный в
консоль, но только на Python 2, и, по крайней мере, это не остановит
сервер после другого исправления. Это безвредно, и это
поведение, существовавшее в прошлом, до того, как я
passthrough_errors изменить.

Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242926832

Отправлено с моего устройства Android с помощью K-9 Mail. Прошу прощения за краткость.

Исправлено в мастере.

Поведение, которое вы описываете, происходит только при включенном PASSTHROUGH_ERRORS, хотя

Да, я пропустил эту деталь. Но это изменение повлияет даже на Python 3, где все это не является проблемой. В Py3, когда включены ошибки сквозной передачи, допустимая ошибка socket.error, вызванная приложением, будет отключена.

мастер вроде wfm, с нетерпением жду следующего релиза, спасибо!

Привет, я использую сервер Werkzeug dev, работающий за NGINX, я столкнулся с той же проблемой, может ли кто-нибудь помочь мне с этим,
11:13:11 web.1 | 127.0.0.1 - - [15/Sep/2016 11:13:11] "GET /api/method/frappe.utils.print_format.download_pdf?doctype=Purchase%20Order&name=PO-00001&format=PO&no_letterhead=0 HTTP/1.1" 200 - 11:13:11 web.1 | Error on request: 11:13:11 web.1 | Traceback (most recent call last): 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi 11:13:11 web.1 | execute(self.server.app) 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 184, in execute 11:13:11 web.1 | write(data) 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 152, in write 11:13:11 web.1 | self.send_header(key, value) 11:13:11 web.1 | File "/usr/lib/python2.7/BaseHTTPServer.py", line 401, in send_header 11:13:11 web.1 | self.wfile.write("%s: %s\r\n" % (keyword, value)) 11:13:11 web.1 | IOError: [Errno 32] Broken pipe

Пожалуйста помоги

Ragav использует другой сервер приложений вместо встроенного в werkzeug dev
сервер, как Gunicorn. На данный момент это единственное решение.

2016-09-15 8:07 GMT + 02: 00 Ragav [email protected] :

Привет, я использую сервер разработчика Werkzeug, работающий за NGINX, я столкнулся с
та же проблема может кто-нибудь помочь мне с этим '',
11:13:11 web.1 | 127.0.0.1 - - [15 / сен / 2016 11:13:11] «ПОЛУЧИТЬ
/api/method/frappe.utils.print_format.download_pdf?
doctype = Купить% 20Order & name = PO-00001 & format = PO & no_letterhead = 0
HTTP / 1.1 "200 -
11:13:11 web.1 | Ошибка по запросу:
11:13:11 web.1 | Отслеживание (последний вызов последний):
11:13:11 web.1 | Файл "/ home / ommi / frappe-bench / env /
lib / python2.7 / site-packages / werkzeug / serve.py ", строка 193, в run_wsgi
11:13:11 web.1 | выполнить (self.server.app)
11:13:11 web.1 | Файл "/ home / ommi / frappe-bench / env /
lib / python2.7 / site-packages / werkzeug / serve.py ", строка 184, при выполнении
11:13:11 web.1 | запись (данные)
11:13:11 web.1 | Файл "/ home / ommi / frappe-bench / env /
lib / python2.7 / site-packages / werkzeug / serve.py ", строка 152, запись
11:13:11 web.1 | self.send_header (ключ, значение)
11:13:11 web.1 | Файл "/usr/lib/python2.7/BaseHTTPServer.py", строка 401,
в send_header
11:13:11 web.1 | self.wfile.write ("% s:% s \ r \ n"% (ключевое слово, значение))
11:13:11 web.1 | IOError: [Errno 32] Сломанная труба

Пожалуйста помоги

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/pallets/werkzeug/issues/954#issuecomment -247243400,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AA6MZ6DNiRIfL91CLeYOoA70W9_nQQzGks5qqOCMgaJpZM4I58cy
.

Руководствуясь недавней фиксацией исправления, я смог решить эту проблему, вызвав app.run с passthrough_errors = False. YMMV

Ошибка, приводившая к сбою, была исправлена ​​в версии 0.12 , выпущенной 21 декабря 2016 года.

  • Отменить изменение поведения, которое привело к сбою сервера разработки, вместо того, чтобы возвращать внутреннюю ошибку сервера (запрос на вытягивание № 2006).

Версия 0.12 была выпущена только на прошлой неделе.

В понедельник, 20 марта 2017 г., в 09:05:00 -0700 Алан Ротман написал:

Ошибка, приводившая к сбою, была исправлена ​​в версии 0.12 , выпущенной 21 декабря 2016 года.

  • Отменить изменение поведения, которое привело к сбою сервера разработки, вместо того, чтобы возвращать внутреннюю ошибку сервера (запрос на вытягивание № 2006).

-
Вы получаете это, потому что изменили состояние открытия / закрытия.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -287807602

Я только что увидел ReleaseNotes сегодня и очень долго ждал этого исправления.

Посмотрите: http://flask.pocoo.org/docs/0.12/changelog/
Версия 0.12
Выпущен 21 декабря 2016 года под кодовым названием Punsch.

https://pypi.python.org/pypi/Flask/0.12
Тип файла Версия Py загружена по размеру
Flask-0.12-py2.py3-none-any.whl (md5) Python Wheel 2.7 2016-12-21 80 КБ
Flask-0.12.tar.gz (md5) Источник 21.12.2016 519KB

Ах да, вы имеете в виду Flask. Конечно.

В понедельник, 20 марта 2017 г., в 09:22:15 -0700 Алан Ротман написал:

Я только что увидел ReleaseNotes сегодня и очень долго ждал этого исправления.

Посмотрите: http://flask.pocoo.org/docs/0.12/changelog/
Версия 0.12
Выпущен 21 декабря 2016 года под кодовым названием Punsch.

https://pypi.python.org/pypi/Flask/0.12
Тип файла Версия Py загружена по размеру
Flask-0.12-py2.py3-none-any.whl (md5) Python Wheel 2.7 2016-12-21 80 КБ
Flask-0.12.tar.gz (md5) Источник 21.12.2016 519KB

-
Вы получаете это, потому что изменили состояние открытия / закрытия.
Ответьте на это письмо напрямую или просмотрите его на GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment -287813405

Просто примечание для тех, кто сталкивается с этой проблемой при запуске flask 0.12.2 на werkzeug в режиме thread = True:
В многопоточном режиме по умолчанию кажется, что каждый поток werkzeug действительно имеет эту проблему, т.е. если вы запрашиваете маршрут, для возврата которого требуется некоторое время, а затем закрываете соединение от клиента, этот конкретный werkzeug регистрирует IOError Broken Pipe, а затем умирает. Сервер в целом продолжает функционировать, за исключением того, что в моем приложении я обнаружил, что это каким-то образом вызывало утечку памяти, когда процесс колбы медленно увеличивался после поломки канала в любом потоке, израсходовал всю оперативную память, а затем SWAP, а затем, наконец, был убит ОС.
Явная отправка passthrough_errors = False в app.run, похоже, решила проблему - потоки больше не умирают, когда клиент отключается, они изящно регистрируют IOError, а затем также регистрируют это (чего я никогда не видел без явной установки passthrough_errors = False):

Exception happened during processing of request from ('127.0.0.1', 50652)
----------------------------------------

После этого сервер продолжает работать в обычном режиме. Мне все еще нужно подождать несколько часов, чтобы увидеть, появится ли снова утечка памяти, но я надеюсь, что этого не произойдет.

На всякий случай это кому-то поможет.

Я тоже видел эту ошибку в контейнере Docker Ubuntu на Kubernetes на виртуальной машине Ubuntu:

Error on request:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 270, in run_wsgi
    execute(self.server.app)
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 261, in execute
    write(data)
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 227, in write
    self.send_header(key, value)
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 412, in send_header
    self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe

Я создал новую виртуальную машину Ubuntu xenial и запустил тот же код в контейнере Ubuntu Docker на Kubernetes, и эта ошибка не была замечена, и Python Flask работал должным образом. Я думаю, это была проблема с моим хостом (Ubuntu VM).

@vhosakot Не могли бы вы сообщить мне, как вы настраиваете конфигурацию приложения? Я столкнулся с аналогичной проблемой в той же среде, что и ваша.

В функции маршрута я использовал другую функцию, предназначенную для маршрутизации.
Я получил данные из ответа этой функции.
Теперь, когда я использовал _loads () _ для этих данных, я получаю сообщение об ошибке.

...
response = get_contents().data
        if response:
            data = loads(response)
..

Ошибка: IOError: [Errno 32] Broken pipe

Была ли эта страница полезной?
0 / 5 - 0 рейтинги