2010-11-23 20 views
1

私はPythonのリソース処理に関するwith文について知っています。 Pythonの例外安全なコードには他にどんな懸念がありますか?Pythonの例外安全性の状態は何ですか?

編集:ここでの懸念は、ファイルなどを開くことです。たとえば、init関数が例外を発生させたとします。初期化されているオブジェクトの状態は何ですか?

+1

あなたはどういうことを言っていますか?何の安全?これはかなり広い話題のようです。あなたの質問は何ですか? – Falmarri

+1

オブジェクトは '__init __()'が呼び出される前にすでに存在しています。これは、通常は 'self'と呼ばれる最初の引数ですが、まだ初期化されていません。そのプロセス中に例外が発生した場合、例外の処理方法や内容によっては、部分的または完全に初期化されないこともあります。 – martineau

+0

ここでは、 '__init __()'メソッドで発生した例外がどのように処理されたかによって、オブジェクトが正しく初期化されなかったことを示しています:![example code](http://dl.dropbox.com/u/5508445/stackoverflow /__init__exception.png)。 – martineau

答えて

5

For instance, suppose an init function raises an exception. What is the state of the object being initialized?

私は、@ S.Lott答えにコメントでそのフラグメントを投稿することができませんでした

ヒント。不確かな場合は、実際に実験を行います。

>>> class Partial(object): 
...  def __init__(self): 
...   self.a= 1 
...   raise Exception 
...   self.b= 2 
... 
>>> p= Partial() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 4, in __init__ 
Exception 
>>> p 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'p' is not defined 

文全体が失敗します。オブジェクトが作成されていません。変数が割り当てられていません。 他に質問がありますか?

C++では、物事ははるかに複雑です。 Pythonでは、オブジェクトは単に破棄されます。

+4

疑問があるときに誰もが実験をしたのであれば、私たちはPythonの質問に比べて非常に良いアドバイスです:-) –

+2

@ THC4k誰かが尋ねていることをしばしば試して結果を投稿すると、固い答え。 Sshhh ...誰にも言わないでください... – JAL

+1

@ THC4k一方、実験だけではなく、より深い知識を身につけるように尋ねると良いです。 –

0

PythonはC++に似ていません。例外は有用なバックトレースを生成します。ユーザーの入力を受けている場合は、適切な例外(例:EOFError)をキャッチします。それ以外の場合は、特別な操作を行う必要はありません。プログラムが予期せぬことをして例外をスローした場合は、結果のスタックダンプを使用して問題をデバッグしてください。非常に高い可用性を実現するには、ログのループ内でtry/exceptを使用して最上位レベルをラップして再起動する必要があります。

+0

強力な例外安全性は、バックトレースなどとは何の関係もありません。例外が発生した場合、システムが一貫性のある状態になっている場合、これが行われます。 Pythonがjavaのような 'try'ブロック内のすべてを実行してからすべての変更を適用しない限り...状態が変更されない限り例外が適用されない限り、Python自体は本質的にS.E.S.はい、S.E.S. C++ではこれもやりにくいです。 「キャッチ」例外を除外できないだけではありません。 – mawalker

3

あなたは言語構造について尋ねている場合:

  • 使用try: except: else:それはあなたが間違った例外をキャッチしないことを保証します。
  • あなたがBaseExceptionをキャッチする前に、よく考えExceptionまたはあなたはイースリーくらいにキャッチすることができますよう except:裸を使用します。
    • あなたのスペルミス - NameError、はImportError
    • あなたのプログラムを終了するユーザの試みを。不完全な実装を示してKeyboardInterrupt、SystemExitを
    • エラー:あなたは、一般的な例外をキャッチすることを決定した場合
  • NotImplementedError log.exception('your message', e)
  • を使ってログインしますStopIterationのような(Pythonで例外は、通常のフロー制御にも使用されていることに注意してください例外)
  • except MyException, myex:の代わりにexcept MyException as myex:という新しい構文を使用します。経験豊富なPython開発者にとっては読みやすいです。あなたが代わりに常にオープンでcodecs.open使用するテキストファイルを読み込む場合は、ファイルについて

    • :編集した質問への

      try: 
          this_doesn_not_exisit(); 
      except Exception: #Don't do that! 
          pass 
      
      print "But this line is still printed" 
      

      回答:ここで

  • はNameErrorキャッチ例ですユニコード文字列を安全に保管できるようにします。
  • __init__については、オブジェクトの状態。 __init__はイニシャライザですので、__init__を呼び出すとオブジェクトが既に存在します。例外を発生させると、フローは中断され、オブジェクトは変数に格納されないため、ガベージコレクションされます。少なくともそれは私の理解です。 MyObject()は何も返さない例外を発生させ、フローが中断され、代入していた値が変更されていない場合に値を返す関数であると考えてください。このうち

チェック:

>>> def throw(): raise Exception() 
... 
>>> a=1 
>>> a=throw() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 1, in throw 
Exception 
>>> a 
1 

ここでは、あなたが__init__で例外を発生させても、オブジェクトが作成されていることを証明する一例です。

>>> global_collection=[] 
>>> class Partial(object): 
... def __init__(self): 
...  self.test="test" 
...  global_collection.append(self) 
...  raise Exception() 
... 
>>> x=Partial() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 5, in __init__ 
Exception 
>>> global_collection 
[<__main__.Partial object at 0xb74f8f6c>] 
>>> global_collection[0].test 
'test' 

UPDATE:によってなさ 含まコメント:@Paulマクガイア、@martineau、@aaronasterling

+0

私は最後にtry:except:else:を追加します。 finally節は、どのエラーがポップアップされたか(一時保存されているかどうかにかかわらず)、ファイルが閉じられ、リソースが解放されることを保証するのに最適です。 http://docs.python.org/reference/compound_stmts.html#try –

+0

FWIWでは、実際に構文エラーを検出することはできません。そのエラーは、プログラムがコンパイルされて実行される前に発生し、 'try'ステートメントはその時点では実行されていません。 – aaronasterling

+0

最初の例で構文エラーはありません。 'this_doesn_not_exisit();'は構文的には問題ありません。しかし、 'this_doesn_not_exisit'という名前がないので、' NameError'例外が発生します。 Aaronが説明したように、「except」も、一般的なものでさえも、「SyntaxError」をキャッチすることはできません(しかし、あなたのアドバイスはそうでなければ一般的に有効です)。 – martineau

関連する問題