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>.