मुझे लगता है कि भी जरूरत खुद के लिए लग रही है। यह मेरा समाधान है। गैर तेजी से पथ ज्यादातर मामलों आप शायद में रुचि रखते हैं को शामिल किया गया।
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
) जो कुछ वैश्विक डाटाबेस वस्तुओं है है और मैं एक बार मैं एक समारोह जो वैश्विक डेटाबेस चर का उपयोग करता है कहा जाता है lazily उन्हें लोड करना चाहता था। मैं आलसी लोडर के साथ ऐसे कार्यों को मैन्युअल रूप से सजा सकता था या मैं स्वचालित रूप से पता लगा सकता हूं कि मेरे 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
एक अन्य समाधान एक वस्तु प्रॉक्सी जो lazily डेटाबेस लोड करता है उपयोग करने के लिए हो गया होता। मैंने इस परियोजना में कहीं और इस्तेमाल किया है, इस प्रकार मैंने इस ऑब्जेक्ट प्रॉक्सी को भी लागू किया है; यदि आप रुचि रखते हैं, तो यहां देखें: utils.py: ObjectProxy
।
यह "उपयोग" की अधिकांश परिभाषाओं के लिए 'निरीक्षण' का भी उपयोग करता है। यदि आपका मतलब "उपयोग" से कुछ और है, तो कृपया विशिष्ट रहें। – delnan
उद्देश्य ग्लोबल्स में सभी अतिरिक्त सामान को बाहर निकालना है। एक कोर लाइब्रेरी है जिसे * के माध्यम से आयात किया जाता है, इसलिए उन सभी की रिपोर्ट करने के लिए बहुत सारे ग्लोबल्स हैं। वास्तव में 'मजेदार' का उपयोग करने के लिए अद्यतन किया गया प्रश्न। –