9
votes

En Python, comment puis-je obtenir les variables globales utilisées dans une fonction?

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()


2 commentaires

Il utilise inspecter 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 .


4 Réponses :


1
votes

Une manière sale serait d'utiliser inspect.getsOrcelines () et de recherche de lignes contenant global . Il n'y a pas de bonnes méthodes pour cela, du moins pas dans inspecter module.


0 commentaires

0
votes

Comme vous l'avez déjà découvert, la propriété f_globals vous donne l'espace de noms global dans lequel la fonction a été définie.

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 , delete_global , etc.


0 commentaires

4
votes

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


3 commentaires

Vous voudrez peut-être mentionner cela nécessite Python 2.6 ou plus.


Merci! Heureusement, j'utilise 2.6 SO test .__ Code __. CO_NAMES é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?



2
votes

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


0 commentaires