Как обработать поврежденный канал (SIGPIPE) в Python?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

47
задан Community 23 May 2017 в 12:09
поделиться

4 ответа

Читайте на попытке: оператор.

try:
    # do something
except socket.error, e:
    # A socket error
except IOError, e:
    if e.errno == errno.EPIPE:
        # EPIPE error
    else:
        # Other error
38
ответ дан John Zwinck 26 November 2019 в 19:39
поделиться

Предположение, что Вы используете стандартный модуль сокета, необходимо ловить socket.error: (32, 'Broken pipe') исключение (не IOError, как другие предположили). Это будет повышено в случае, который Вы описали, т.е. отправляющий/пишущий к сокету, для которого разъединилась удаленная сторона.

import socket, errno, time

# setup socket to listen for incoming connections
s = socket.socket()
s.bind(('localhost', 1234))
s.listen(1)
remote, address = s.accept()

print "Got connection from: ", address

while 1:
    try:
        remote.send("message to peer\n")
        time.sleep(1)
    except socket.error, e:
        if isinstance(e.args, tuple):
            print "errno is %d" % e[0]
            if e[0] == errno.EPIPE:
               # remote peer disconnected
               print "Detected remote disconnect"
            else:
               # determine and handle different error
               pass
        else:
            print "socket error ", e
        remote.close()
        break
    except IOError, e:
        # Hmmm, Can IOError actually be raised by the socket module?
        print "Got IOError: ", e
        break

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

можно уменьшить падение (но не полностью устранить) этого при помощи select.select() (или poll). Проверьте на данные, готовые читать от коллеги прежде, чем делать попытку записи. Если select отчеты, что существуют доступные данные для чтения из сокета однорангового узла, читают его с помощью socket.recv(). Если это возвращает пустую строку, удаленный узел закрыл соединение. Поскольку существует все еще состояние состязания здесь, необходимо будет все еще поймать и обработать исключение.

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

53
ответ дан mhawke 26 November 2019 в 19:39
поделиться

SIGPIPE (хотя я думаю, возможно, что Вы имеете в виду EPIPE?) происходит на сокетах, когда Вы закрываете сокет и затем отправляете данные в них. Простое решение не должно завершать работу сокета прежде, чем попытаться отправить ему данные. Это может также произойти на каналах, но это не кажется, что это - то, что Вы испытываете, так как это - сетевой сервер.

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

, Конечно, если бы Вы использовали Скрученный вместо того, чтобы породить новый поток для каждого соединения клиента, у Вас, вероятно, не было бы этой проблемы. Действительно трудно (возможно, невозможный, в зависимости от Вашего приложения) получить упорядочивание операций закрытия и операций записи, корректных, если несколько потоков имеют дело с тем же каналом ввода-вывода.

3
ответ дан Glyph 26 November 2019 в 19:39
поделиться

Мой ответ очень близко к S.Lott's, кроме я был бы еще более конкретным:

try:
    # do something
except IOError, e:
    # ooops, check the attributes of e to see precisely what happened.
    if e.errno != 23:
        # I don't know how to handle this
        raise

, где "23" код ошибки, Вы добираетесь от EPIPE. Таким образом, Вы не попытаетесь обработать ошибку полномочий или что-либо еще, для чего Вы не снабжены.

-3
ответ дан Kirk Strauser 26 November 2019 в 19:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: