2010-12-19 19 views
45

サブ関数を持つ関数でexecを使用できないようです...execがサブ関数を持つ関数で動作しないのはなぜですか?

誰でもこのPythonコードが機能しないのは知っていますか?私はtest2のexecでエラーが発生します。また、私はエグゼクティブが良いスタイルではないことを知っていますが、私を信頼してください、私は適切な理由でエグゼクティブを使用しています。私はそれ以外の場合は使用しません。

#!/usr/bin/env python 
# 

def test1(): 
    exec('print "hi from test1"') 

test1() 

def test2(): 
    """Test with a subfunction.""" 
    exec('print "hi from test2"') 
    def subfunction(): 
     return True 

test2() 

EDIT:サブ機能にバグを絞り込んだ。これはraiseキーワードとは関係ありません。

+0

'import * from ... 'にも同じ制限があります。 – osa

+0

は私には見えますが、補語はサブ関数と見なされます。 – dbliss

答えて

58

正しい。コンテキストを指定しない限り、サブ関数を持つ関数でexecを使用することはできません。

のexec関数で使用され、 機能が 自由変数を持つネストされたブロックが含まれている場合のexec が明示的に幹部のためのローカル 名前空間を指定しない限り、コンパイラは にSyntaxErrorを発生させます:ドキュメントから。 (「NSでのexec objは」法的になり、他の の言葉で、「EXEC objは」違法となり、 けど。)

それは日曜日でなかった場合、私はおそらく理解するであろう。このために良い理由があります夜。 次の質問:なぜあなたはexecを使用していますか?非常にめったに必要ありません。あなたは正当な理由があると言います。私はそれについて懐疑的だと感じている。 ;)あなたが正当な理由があるなら、回避策を教えてあげます。 :-P

まあ、ここはとにかくです:

def test2(): 
    """Test with a subfunction.""" 
    exec 'print "hi from test2"' in globals(), locals() 
    def subfunction(): 
     return True 
+0

Pythonへの非常に低レベルのバインディングしか持たない難解なNoSQLデータベース用の人道的でオブジェクト指向のAPIを実装することが一例です。 あなたにはもう一つ質問があります:「exec」コードを特定のクラスに注入する方法はありますか?はいの場合、どうですか? – chiffa

+1

@AndreiKucharavyいいえ、 'exec'はコードを実行するので、注入する" exec "コードはありません。実行されたコードは実行されたコードです。コードをコンパイルして挿入することができます。しかし、通常はコンパイルする必要はありません。ただ注入するだけです。 OO APIをNoSQL DBにしたいだけなので、何かexecをしなければならないという明白な理由はありません。 –

+0

申し訳ありませんが、私の悪い:コードを挿入するのではなく、それを挿入するので、特定のクラスの一部として呼び出すことができます。アイデアは、ユーザーが作成した設定ファイルを解析し、定義から単純なpythonオブジェクトとして呼び出し可能なオブジェクトのファミリを生成しますが、フードの下にはSQLAlchemyのようなデータベースとのバッファリングインターフェイスを実装しますが、すべてのマッピングとオブジェクト定義コードを明示的に記述します。 – chiffa

1

エラーが私にはかなり明白であるように思わ:

SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variables 

を参照してください詳細はPEP 227:プリントを使用するには、print文を修正した後、Pythonの3.1.3でうまく機能http://www.python.org/dev/peps/pep-0227/

4

関数。

Python 2.6では、SyntaxError: unqualified exec is not allowed in function 'test2' it contains a nested function with free variablesが生成されていますが、バグではないと思います。

24

Pythonで、それはローカル変数は辞書locals()に格納されている種類のように見えますが、彼らは通常はありません。代わりに、それらは主にスタックに格納され、インデックスによってアクセスされます。これにより、毎回辞書検索をしなければならない場合よりも、ローカル変数検索が高速になります。 locals()関数を使用すると、すべてのローカル変数から作成された新鮮な辞書が得られます。そのため、locals()への代入は一般的には機能しません。

このシナリオには例外がいくつかあります:

あなたはPythonが最適化をオフにし、ローカル変数の実際の辞書を使用して関数内で修飾されていないexecを使用する場合。つまり、execの内部から変数を作成または更新できますが、その関数内のすべてのローカル変数へのアクセスがより遅く実行されることを意味します。

もう1つの例外は、関数をネストすると、内部関数は外部関数スコープのローカル変数にアクセスできます。これを行うと、変数はスタックに格納されるのではなく、「セル」オブジェクトに格納されます。インダイレクションの余分なレベルは、スコープ付き変数のすべての使用を、内部関数または外部関数からアクセスするかどうかにかかわらず、より遅くします。

あなたが遭遇したキャッチは、ローカル変数が通常どのように格納されるかという2つの例外が互換性がないということです。変数を辞書に格納したり、同時にセル参照でアクセスすることはできません。 Python 2.xは、スコープ付き変数を使用しようとしていない場合でも、execを許可しないことでこれを修正しています。

2

は、これはかなり興味深いケースである:

>>> def func(): 
...  exec('print "hi from func"') 
...  def subfunction(): 
...   return True 
... 
    File "<stdin>", line 2 
SyntaxError: unqualified exec is not allowed in function 'func' because 
it contains a nested function with free variables 

これはsubfunctionが自由変数が含まれていることである、とPython 2であるため、execは、理論的には含むで地元の人々を変更することができ、実際に動作しない理由変数がグローバル関数スコープまたは親関数スコープからバインドされるべきかどうかを判断することは不可能です。 PythonのZenの節の1つはです。「あいまいさに直面して、推測する誘惑を拒否してください。」これはPython 2の機能です。

ここで、問題は、この非結合変数は何ですか?さて、それはTrueです!

確かにそれはNoneで再生可能です:Noneがに割り当てることができないにもかかわらず

>>> def func(): 
...  exec('print "hi from func"') 
...  def subfunction(): 
...   return None 
... 
    File "<stdin>", line 2 
SyntaxError: unqualified exec is not allowed in function 'test2' because it contains a nested 
function with free variables 

、それはバイトコードで定数とみなされ、バグのパーサは、それはここに結合していない変数であると考えています。

しかし、あなたが1と交換し、それが問題なく動作するかどうか:

>>> def test2(): 
...  exec('print "hi from func"') 
...  def subfunction(): 
...   return 1 
... 
>>> 

明示的execで使用されるグローバル、おそらく地元の人を指定し、このエラーを回避するには、言う:

>>> def test2(): 
...  exec 'print "hi from test2"' in {} 
...  def subfunction(): 
...   return None 
... 
>>> 

execは、単純な関数であり、パーサまたはバイトコードコンパイラによって特別に処理されません。 Python 3ではexecは関数ローカル名を再バインドできないため、このSyntaxErrorとあいまい性は存在しません。 3互換性対のPython 2で


一つ特有場合は、Python 2.7 documentationフォームexec(expr, globals, locals)exec expr in globals, localsと等価である

形態exec(expr, globals)が、exec expr in globalsと同等であることを述べながら、ということです。 execのタプル形式は、Python 3との互換性を提供します。execはステートメントではなく関数です。

タプルの形式は、a bug in handling of exec in functions with nested functions (issue 21591)のように、常に100%互換ではありませんでした。 Python 2.7.8まで、次のコードで例外がスローされた可能性があります。

def func(): 
    exec('print "hi from test2"', {}) 
    def subfunction(): 
     return None 

これはPython 2.7で修正されました。9そしてそれはもはや投げません。

+1

Python2/Python3 * exec *のバグと互換性の不都合を避けるため、イディオム 'edict = {};を使うこともできます。 eval(コンパイル(文、 ''、 'exec')、globals()、edict) '。 これは、* exec *の副作用へのアクセスを提供します([このディスカッションはexec/eval/compile](http://stackoverflow.com/a/29456463/2127439を参照))。 – wolfmanx

関連する問題