2012-09-21 77 views
1

標題似乎很愚蠢,但我不知道如何精確地表達它,抱歉。Python:如何訪問eval的全局變量()裏面的eval

我有一個程序,需要評估一些用戶代碼(通過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) 

這會給resut:

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

使用 '全局()' 在這裏insde '犯錯' 當然是錯誤的。但是我怎麼能在'err'裏面得到'g'的值呢?

回答

1

從函數內部對globals()的任何引用將始終爲您提供定義該函數時在範圍內的全局變量。這裏所看到的與從一個模塊導入另一個模塊時沒有什麼不同:導入的函數仍然引用定義模塊的全局變量。

使用g作爲其globals()函數的最簡單方法是使用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 
>>> 
+0

是的,這就是我要找的。我使用檢查模塊來達到同樣的效果。 – jayven

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