18

例外を発生させるPythonに複数行があるとします。

Python はどの行に対して例外を発生させるかをどのように決定しますか?

例: (注:\各行の後にバックスラッシュを使用することもできました)

(1
 +0/0
 +3)

3 行目に例外があります(ZeroDivisionError例外、 at +3))。

(1
 +
 0/0
 )

3 行目で例外をスローします。

(0/0
 +
 1)

2 行目で例外をスローします。

この質問はこの例に触発されたもので、@Godmanは例外が最後の行で発生するだけではないことを指摘しました (私が以前考えていたように)。

4

2 に答える 2

4

基本的に、私たち全員が正しい方向に考えているとは思いません。ここには最後の行のようなものはありません。例外は、式を完全に受け取ると、インタープリターによって発生します。Python の文法: http://docs.python.org/reference/grammar.htmlによると、式は閉じ括弧 ')' を押すまで完全には完成しません。同じことについての簡単な説明は、質問自体に対するコメントで Joran Beasley によって与えられました。

文法を深く掘り下げることなく、これの正しさを判断するために3つのことを行うことができます:-

  1. 次のコードを Python インタープリターで記述します。

    a=(1+2+0/0+4+5)

これにより、ZeroDivionError も発生します。

  1. 次のコードを Python インタープリターで記述します。

    a=(1+2+0/0+4+5 # そしてエンターを押す

式が完全ではなく、インタープリターで解析できないため、これにより無効な構文が得られます PS: これは、質問で言及されているコードと同じです

  1. 次のコードを Python インタープリターで記述します。

a = (1
+2
+0/0
+4
+5)

最終的に、右中かっこを押すまで式は完了しません。したがって、例外を取得することなく、サブ式を内部に追加し続けることができます。したがって、基本的に、インタプリタはこれをすべて行番号として認識しません。すべての式 (サブ式を含む) が完了するまで待機します。そして、それはインターピーターのための適切なプログラミング制御フローです。

PS:回答の書式設定を許してください。

新しい編集:-

@ Hayden: 文法を深く掘り下げないことで、機微を説明するのは簡単だと思いました。ただし、参考までに、URL からコードをコピーしているだけです: http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html

実行する手順:- 1. 質問で尋ねられたコードを temp.py ファイルに記述して保存し、temp を別のファイルまたはインタープリターにインポートします。これにより、temp.pyc 2 が作成されます。次に、上記の URL の完全なコードをコピーして byteCodeDetails.py に貼り付け、コマンド プロンプトでファイルを python byteCodeDetails.py temp.pyc として実行します。関数 show_file がここで呼び出され、次の出力が得られます。

MAGIC 03F30D0A MODDATE
458C2E50(FRI AUG 17 23:54:05 2012)Code ArgCount 0 Nlocals 0
stacksize
3 Flags 0040 Code
640600640200640200151764030017640400175a000500050050500050005000500050005000500050005000500050005000500050005000500050005000500050005000500050005000500050005000500050005000500 LOAD_CONST 3 (4) 14 BINARY_ADD 15 LOAD_CONST 4 (5) 18 BINARY_ADD 19 STORE_NAME 0 (a) 22 LOAD_CONST 5 (なし)












25 RETURN_VALUE
consts
1
2
0
4
5
なし
3 つ
の名前 ('a',)
varnames ()
freevars ()
cellvars ()
ファイル名 'C:\Users\Python\temp1.py'

名前 ''
firstlineno 5
lnotab


だから、あなたが気づくことができるように: -

  1. 上記のリンクからの引用: 逆アセンブルされた出力では、左端の数字 (1、2、3) は元のソース ファイルの行番号であり、次の数字 (0、3、6、9、...) です。命令のバイトオフセットです。同様に、あなたのコードでは、一番左の数字は行番号である 5 だけであり、右側の列はコードのコンパイラによって変換されたニーモニック (インタープリターによって読み取られる) を表します。が形成され、それらの形成は、コンパイルされたコードの行番号の値に取って代わられます。
  2. firstlineno は 5 を指します。

次に、temp.py ファイルの初期コードを少し変更します。

a = (1
+2
+0/0
+4 +
5)

ここで、上記の 2 つの手順をもう一度実行します。以下は出力です: -

MAGIC 03F30D0A MODDATE
0F8E2E50(SAT AUG 18 00:01:43 2012) コード
ArgCount
0
Nlocals 0 Stacksize 3
Flags

0040
Code
640600640200640200151764030017640400175a006405005005005005004050050050050050050040534050034
0

0 LOAD_CONST 3 (4) 14 BINARY_ADD




5 15 LOAD_CONST 4 (5)
18 BINARY_ADD
19 STORE_NAME 0 (a)
22 LOAD_CONST 5 (なし)
25 RETURN_VALUE
consts
1
2
0
4
5
なし
3 つ
の名前 ('a',)
varnames ()
freevars ()
cellvars ()
filename 'C :\Users\Python\temp1.py'
名前 ''
firstlineno 4

lnotab 0f01

さて、これで 2 つのことがはっきりとわかります:-

  1. バイトコードは、'code 640600640200640200151764030017640400175a000064050053' の次の行に示されているように、'4' と '5' で始まる 2 行で構成されます。これは、コンパイラが .py ファイルを解析し、temp.py のコードをインタープリターによって実行される 2 行のコードに変換したことを示しています。ここで、4 行目の内容は、式が完成しているかどうかに関係なく、インタープリターによって実行されることに注意してください。
  2. firstlinenoの値が5 ではなく 4 に変更されます

この長い議論の要点は、バイトコードがインタプリタに対して行の開始位置と、この行に対して実行されるべき対応するステートメントを示す場合、インタプリタはその行と次に記述された対応するステートメントを実行するだけであるということです。それに。

質問のコードでは、firstlineno が 5 と表示されているため、5 行目にエラーが表示されます。うまくいけば、これが役に立ちます。

于 2012-08-17T11:52:09.430 に答える
1

例外は、次のいずれかを含む行* を指します。

  1. 最後の演算子(前のリテラル/演算子が例外を引き起こした場合)。

  2. 最後のリテラル(そうでない場合、最後のリテラル/演算子が例外を引き起こした)。

.

ただし、これが表示される動作でない場合は、いずれかの py (ソース) ファイルと、それに対応する (コンパイルされた) pyc ファイル、または実行中のコード (メモリ内) の不一致が原因である可能性があります。以下は説明のための例です。

  • 以下E.pyが含まれているとします。

    def z():
        0/0
    
  • Python コマンド ラインから(これはbyte-code:にimport Eコンパイルされ、メモリに格納されます)。E.pyE.pyc

  • E.z()の 2 行目で例外を生成する を呼び出すと、z次の行が表示さ0/0れます。これは驚くことではありません。

  • ソース ファイルに戻りE.py、先頭に 2 行を挿入し、2 行目に文字列 を挿入します"oh dear, oh dear"

  • Python コマンド ラインに戻り、もう一度呼び出しますE.z()

  • 例外 ( zの 2 行目) が表示されるようになり"oh dear, oh dear"ました。

*更新:これに関する参照はありません。見つけた場合はコメントしてください。私は以前、それが単に最後の行だと思っていました!

于 2012-08-17T11:05:25.317 に答える