我需要還自己。這是我的解決方案。非快速路徑覆蓋大多數情況下,你都可能感興趣。
def iterGlobalsUsedInFunc(f, fast=False, loadsOnly=True):
if hasattr(f, "func_code"): code = f.func_code
else: code = f
if fast:
# co_names is the list of all names which are used.
# These are mostly the globals. These are also attrib names, so these are more...
for name in code.co_names:
yield name
else:
# Use the disassembly. Note that this will still not
# find dynamic lookups to `globals()`
# (which is anyway not possible to detect always).
import dis
ops = ["LOAD_GLOBAL"]
if not loadsOnly:
ops += ["STORE_GLOBAL", "DELETE_GLOBAL"]
ops = map(dis.opmap.__getitem__, ops)
i = 0
while i < len(code.co_code):
op = ord(code.co_code[i])
i += 1
if op >= dis.HAVE_ARGUMENT:
oparg = ord(code.co_code[i]) + ord(code.co_code[i+1])*256
i += 2
else:
oparg = None
if op in ops:
name = code.co_names[oparg]
yield name
# iterate through sub code objects
import types
for subcode in code.co_consts:
if isinstance(subcode, types.CodeType):
for g in iterGlobalsUsedInFunc(subcode, fast=fast, loadsOnly=loadsOnly):
yield g
一個更新的版本可能here。
我的使用情況:
我有一些模塊(songdb
),其中有一些全局數據庫對象,我想懶洋洋地加載它們一次我叫它使用全局數據庫變量的函數。我可以用懶惰的加載程序手動修飾這些函數,或者我可以通過我的iterGlobalsUsedInFunc
函數自動檢測哪些函數需要它。
這基本上是代碼(full code;實際上延長了類現在),其中init
自動裝飾這樣的功能:
DBs = {
"songDb": "songs.db",
"songHashDb": "songHashs.db",
"songSearchIndexDb": "songSearchIndex.db",
}
for db in DBs.keys(): globals()[db] = None
def usedDbsInFunc(f):
dbs = []
for name in utils.iterGlobalsUsedInFunc(f, loadsOnly=True):
if name in DBs:
dbs += [name]
return dbs
def init():
import types
for fname in globals().keys():
f = globals()[fname]
if not isinstance(f, types.FunctionType): continue
dbs = usedDbsInFunc(f)
if not dbs: continue
globals()[fname] = lazyInitDb(*dbs)(f)
def initDb(db):
if not globals()[db]:
globals()[db] = DB(DBs[db])
def lazyInitDb(*dbs):
def decorator(f):
def decorated(*args, **kwargs):
for db in dbs:
initDb(db)
return f(*args, **kwargs)
return decorated
return decorator
另一種解決方案將是使用哪個懶散地加載數據庫中的對象的代理。我在這個項目的其他地方使用過,因此我也實現了這樣的對象代理;如果你有興趣,請看這裏:utils.py:ObjectProxy
。
對於「使用」的大多數定義,它也使用'inspect'。如果你的意思是「使用」的其他內容,請具體說明。 – delnan 2011-03-25 17:02:55
目的是爲了挑選出全局中所有額外的東西。有一個通過*導入的核心庫,所以有太多的全局變量來報告它們。更新了實際使用'fun'的問題。 – 2011-03-25 18:25:51