1

タイトルはばかげているようですが、正確に表現する方法がわかりません。ごめんなさい。

(セキュリティのためにRestrictedPythonを介して)ユーザーコードを評価する必要があるプログラムがあり、evalのグローバルに関数を入れて、eval時にデバッグ情報を出力できるようにします(簡略化)。

class UserException(Exception):
    pass


def err(msg):
    # ? how to get the globals variable in eval ?
    A = globals().get('A', 'A not found')
    return UserException("%s and A's value is %r" % (msg, A))

g = {
    'err': err,
    'A': None,
    '__builtins__': {},
}

print eval('A or err("A not true")', g)

これにより、結果が得られます。

A not true and A's value is 'A not found'

ここで「globals()」を使用すると、「err」はもちろん間違っています。しかし、どうすれば「err」内の「g」の値を取得できますか?

4

2 に答える 2

1

gデフォルトの引数として渡すことができます。

def err(msg, g=g):
    A = g['A']
    return UserException("%s and A's value is %r" % (msg, A))

結果が得られます:A not true and A's value is None

于 2012-09-21T09:18:16.080 に答える
1

関数内からの参照globals()は、関数が定義されたときにスコープ内にあったグローバルを常に提供します。ここに表示されているのは、あるモジュールから別のモジュールに関数をインポートする場合と同じです。インポートされた関数は、それが定義されたモジュールのグローバルを引き続き参照します。

関数をそのまま使用する最も簡単な方法は、グローバル変数として使用しgglobals()定義を実行することです。g関数のグローバルを変更する場合は、関数が使用する他のグローバルも含める必要があります。この場合UserException

err()または、呼び出し元のスタックフレームを検査して、呼び出し元のグローバルを使用することもできます。それは厄介ですが、デバッグ用の場合は情報が受け入れられる可能性があります。

>>> def err(msg):
    # ? how to get the globals variable in eval ?
    A = sys._getframe(1).f_globals.get('A', 'A not found')
    return UserException("%s and A's value is %r" % (msg, A))

>>> import sys
>>> g = {
    'err': err,
    'A': None,
    '__builtins__': {},
}
>>> print eval('A or err("A not true")', g, g)
A not true and A's value is None
>>> 
于 2012-09-21T10:30:00.037 に答える