我需要还自己。这是我的解决方案。非快速路径覆盖大多数情况下,你都可能感兴趣。
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