J'essaie de collecter des informations sur des accidents et j'ai du mal à comprendre comment obtenir les globaux utilisés dans la fonction écrasée.
import inspect
fun = 222
other = "junk"
def test():
global fun
harold = 888 + fun
try:
harold/0
except:
frames = inspect.trace()
print "Local variables:"
print frames[0][0].f_locals
print "All global variables, not what I want!"
print frames[0][0].f_globals
test()
4 Réponses :
Une manière sale serait d'utiliser inspect.getsOrcelines () code> et de recherche de lignes contenant global inspecter code> module. P>
Comme vous l'avez déjà découvert, la propriété De ce que je peux voir, le seul moyen de savoir quelles variables globales sont utilisées consiste à désassembler le code d'octet de la fonction avec DIS ; Recherchez les codes d'octets Store_Name , store_global , f_globals code> vous donne l'espace de noms global dans lequel la fonction a été définie. P>
Vérifiez ceci out
a = 10
def test():
global a
a = 12
b = 12
print "co_argcount = ",test.__code__.co_argcount
print "co_cellvars = ",test.__code__.co_cellvars
print "co_code = ",test.__code__.co_code
print "co_consts = ",test.__code__.co_consts
print "co_filename = ",test.__code__.co_filename
print "co_firstlineno = ",test.__code__.co_firstlineno
print "co_flags = ",test.__code__.co_flags
print "co_freevars = ",test.__code__.co_freevars
print "co_lnotab = ",test.__code__.co_lnotab
print "co_name = ",test.__code__.co_name
print "co_names = ",test.__code__.co_names
print "co_nlocals = ",test.__code__.co_nlocals
print "co_stacksize = ",test.__code__.co_stacksize
print "co_varnames = ",test.__code__.co_varnames
Vous voudrez peut-être mentionner cela nécessite Python 2.6 ou plus.
Merci! Heureusement, j'utilise 2.6 SO test .__ Code __. CO_NAMES CODE> était exactement ce que je cherchais. Dans ce cas particulier, je décoriez des fonctions pour les gérer si elles échouent, j'ai donc la fonction à portée de main.
Comment obtenir la valeur de la variable trouvée via CO_NAMES?
J'avais besoin de ça aussi moi-même. C'est ma solution. Le chemin non rapide couvre la plupart des cas que vous êtes probablement intéressé.
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
Il utilise
inspecter code> aussi, pour la plupart des définitions de "utilisation". Si vous voulez dire autre chose en «utilisation», s'il vous plaît être précis.Le but est de calmer toutes les choses supplémentaires dans les globaux. Il y a une bibliothèque principale importée via * il y a donc beaucoup trop de globaux pour les signaler. Question mise à jour pour utiliser réellement
amusant code>.