2009-05-12 4 views
-2

除いに比較されますか?方法は、例外は、次のコードセグメントで句

周囲の遊びから、isinstanceの下に電話があるようですが、これは正しいですか?

私はプロセスを破壊しようとしているので、具体的には、実際にFredのインスタンスではないにもかかわらず、execred FredによってキャッチされるBobを構築できるようにしたいと思っています。サブクラス。私はこれをやろうとしている理由

人のカップルが、私たちは、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

-1:将来のメンテナーを意図的に混乱させる明白で明白なPythonの機能を覆す。 –

答えて

6

私はあなたの推測は正しいと思われ、傍受する唯一の方法はFredを基本クラスとしてBobに追加することだと思います。たとえば:

# 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

私は、それが実際に フレッドのインスタンスまたはその サブクラスのいずれかでなくてもexecpt フレッドによって捕捉されることをボブ などを構築できるようにしたいです。

まあ、「例外」を捕まえることはできますが、これはあまり有名ではありません。正しい例外をキャッチし、最後の手段として一般的な例外(すべての例外がサブクラス化されている)に戻ってください。これはあなたのために動作しない場合、何かがあなたの設計段階でひどく間違っていた。

See this note from Code Like A Pythonista

注:常に キャッチする例外を指定します。裸のexcept節は使用しないでください。 ベア以外の句は の予期しない例外をキャッチし、 のコードをデバッグするのが非常に困難です。

しかし、パイソンの禅におけるイディオムの一つは

特別な場合は、ルールを破るのに十分な特別ではないです。 実用性は純度を上回りますが。

1
>>> 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)

参照するには同様のロジックを実装している必要があり、これはあなたが、wateverを実装する方法ですあなたは欲しい。もちろん、のinitではありませんが、他の方法もあります。

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

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


blah 
0

少なくともCPythonでは、タイプ10(例外一致)のCOMPARE_OP操作があるようです。あなたはその計算をハックすることはできません。

 
>>> 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 
1

「シームレスな」哲学を遵守しているsocket.timeoutの例外を隠す方法がわかりません。期待どおりの例外をキャッチするのは何が問題なのですか?

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

それとも、あなたが本当にsocket.timeoutとしてそれをキャッチしたい場合は、なぜちょうどour_proxy_helper_classでsocket.timeoutを上げていませんか?

raise socket.timeout('Method x timeout') 

したがって、our_proxy_helper_classにsocket.timeoutを設定すると、「except socket.timeout」によってキャッチされるはずです。

+0

シームレスには、ローカルコードとリモートコードの間の唯一の目に見える違いがインポートであることを意味します。 "import socket"を使用してソケットをローカルにインポートした場合、socket.timeoutを除いては、リモートでインポートするときに同じ処理を行うのが理想的です。 –

+0

この例では、socket.timeoutはクラスではありません。イントロスペクションをしない限り、見た目はクラスのように機能します。しかし、実際には別のプロキシヘルパーインスタンスです。私はこれがコアの問題だと考えています。メタクラスを実際のクラスに変換する方法としてメタクラスを調べています。それから私はそのクラスのインスタンスとして例外を発生させることができ、すべてが期待どおりに動作するはずです。 –

関連する問題