как сравниваются исключения в исключении - PullRequest
0 голосов
/ 12 мая 2009

В следующем сегменте кода:

try:
    raise Bob()
except Fred:
    print "blah"

Как осуществляется сравнение Боба и Фреда?

Из-за того, что ты играешь вокруг, кажется, что это вызов ininstance внизу, это правильно?

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

Несколько человек спросили, почему я пытаюсь это сделать ...

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

import remobj
socket = remobj.RemObj("remote_server_name").getImport("socket")
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("", 0))
print "listening on port:", s.getsockname()[1]
s.settimeout(10)
try:
    print "received:", s.recv(2048)
except socket.timeout:
    print "timeout"

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

Ответы [ 5 ]

6 голосов
/ 12 мая 2009

Я считаю, что ваше предположение верно в том, как работает сравнение, и единственный способ перехватить это добавить Фреда в качестве базового класса для Боба. Например:

# Assume both Bob and Fred are derived from Exception
>>> class Bob(Bob, Fred):
...     pass
... 
>>> try:
...     raise Bob()
... except Fred:
...     print 'blah'
blah

Насколько я знаю, это единственный способ заставить его работать так, как вы его написали. Однако, если вы просто переписали строку исключений: как

... except (Bob, Fred):

Он поймал бы и Боба, и Фреда, не требуя изменения определения Боба.

1 голос
/ 13 мая 2009

Мне непонятно, как сокрытие вашего исключения в socket.timeout придерживается "бесшовной" философии? Что не так с перехватом ожидаемого исключения, как оно определено?

try:
    print "received:", s.recv(2048)
except socket.timeout:
    print "timeout"
except our_proxy_helper_class:
    print 'crap!'

Или, если вы действительно хотите перехватить его как socket.timeout, почему бы просто не вызвать socket.timeout в our_proxy_helper_class?

raise socket.timeout('Method x timeout')

Поэтому, когда вы вызываете socket.timeout в our_proxy_helper_class, он должен быть перехвачен как "кроме socket.timeout".

1 голос
/ 12 мая 2009
>>> class Fred(Exception):
    pass
>>> class Bob(Fred):
    pass
>>> issubclass(Bob, Fred)
True
>>> issubclass(Fred, Bob)
False
>>> try:
    raise Bob()
except Fred:
    print("blah")


blah

Таким образом, в основном исключение поймано, потому что Боб является подклассом Фреда, я полагаю, либо они реализовали логику, подобную issubclass(Bob, Fred)

Видите, это то, как вы хотите реализовать, что хотите. Конечно, не в init , а в другом методе.

>>> class Bob(Exception):
    def __init__(self):
        raise Fred

>>> try:
    b = Bob()
except Fred:
    print('blah')


blah
1 голос
/ 12 мая 2009

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

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

См. Это примечание от Code Like A Pythonista

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

Однако, одна из идиом в дзен Python -

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

0 голосов
/ 13 мая 2009

По крайней мере, в CPython похоже, что есть операция COMPARE_OP с типом 10 (исключение соответствует). Вы вряд ли сможете что-то сделать, чтобы взломать этот расчет.

>>> import dis
>>> def foo():
...     try:
...             raise OSError()
...     except Exception, e:
...             pass
... 
>>> dis.dis(foo)
  2           0 SETUP_EXCEPT            13 (to 16)

  3           3 LOAD_GLOBAL              0 (OSError)
              6 CALL_FUNCTION            0
              9 RAISE_VARARGS            1
             12 POP_BLOCK           
             13 JUMP_FORWARD            21 (to 37)

  4     >>   16 DUP_TOP             
             17 LOAD_GLOBAL              1 (Exception)
             20 COMPARE_OP              10 (exception match)
             23 JUMP_IF_FALSE            9 (to 35)
             26 POP_TOP             
             27 POP_TOP             
             28 STORE_FAST               0 (e)
             31 POP_TOP             

  5          32 JUMP_FORWARD             2 (to 37)
        >>   35 POP_TOP             
             36 END_FINALLY         
        >>   37 LOAD_CONST               0 (None)
             40 RETURN_VALUE        
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...