2009-12-01 10 views
10

में एक विशिष्ट मॉड्यूल पर निर्भर मॉड्यूल की सूची कैसे खोजें मेरे पायथन आधारित वेब एप्लिकेशन के विकास के समय को कम करने के लिए, मैं हाल ही में संशोधित मॉड्यूल के लिए पुनः लोड() का उपयोग करने की कोशिश कर रहा हूं। रीलोड() एक समर्पित वेब पेज (वेब ​​ऐप के विकास संस्करण का हिस्सा) के माध्यम से होता है जो मॉड्यूल को सूचीबद्ध करता है जिसे हाल ही में संशोधित किया गया है (और पीई फाइल का संशोधित समय टिकट संबंधित पीईसी फाइल के बाद है)। मॉड्यूल की पूरी सूची sys.modules से प्राप्त की जाती है (और मैं केवल उन मॉड्यूल पर ध्यान केंद्रित करने के लिए सूची फ़िल्टर करता हूं जो मेरे पैकेज का हिस्सा हैं)।पाइथन

व्यक्तिगत पायथन फ़ाइलों को फिर से लोड करना कुछ मामलों में काम करता है, न कि अन्य मामलों में। मुझे लगता है, संशोधित मॉड्यूल पर निर्भर सभी मॉड्यूल को पुनः लोड किया जाना चाहिए और पुनः लोडिंग उचित क्रम में होनी चाहिए।

मैं एक विशिष्ट मॉड्यूल द्वारा आयातित मॉड्यूल की सूची प्राप्त करने का एक तरीका ढूंढ रहा हूं। क्या Python में इस तरह के आत्मनिरीक्षण करने का कोई तरीका है?

मैं समझता हूं कि मेरा दृष्टिकोण 100% गारंटी नहीं हो सकता है और सबसे सुरक्षित तरीका सबकुछ फिर से लोड करना होगा, लेकिन यदि अधिकांश मामलों के लिए एक तेज दृष्टिकोण काम करता है, तो यह विकास उद्देश्यों के लिए पर्याप्त होगा।

Django autoreloader

@Glenn मेनार्ड, Thanx के बारे में टिप्पणी करने के लिए प्रतिक्रिया, मैं Django के autoreloader के बारे में पढ़ा था। मेरा वेब ऐप ज़ोप 3 पर आधारित है और पैकेजों की मात्रा और ज़ेडसीएमएल आधारित प्रारंभिकरणों के साथ, डेटाबेस पुनर्विक्रय बड़ा होने पर कुल पुनरारंभ लगभग 10 सेकंड से 30 सेकंड या उससे अधिक समय लेता है। मैं पुनरारंभ के दौरान बिताए गए इस समय पर कटौती करने का प्रयास कर रहा हूं। जब मुझे लगता है कि मैंने बहुत सारे बदलाव किए हैं, तो मैं आमतौर पर पूर्ण पुनरारंभ करना पसंद करता हूं, लेकिन अक्सर मैं यहां और वहां कुछ पंक्तियों को बदल रहा हूं जिसके लिए मैं इतना समय बिताना नहीं चाहता हूं। विकास सेटअप उत्पादन सेटअप से पूरी तरह से स्वतंत्र है और आमतौर पर अगर पुनः लोड में कुछ गलत होता है, तो यह स्पष्ट हो जाता है क्योंकि एप्लिकेशन पेज अजीब जानकारी दिखाने या अपवाद फेंकने लगते हैं। चुनिंदा रीलोड काम करेगा या नहीं, यह जानने में बहुत दिलचस्पी है।

+0

Django के ऑटोरेलोडर की तरह कुछ करना अधिक सुरक्षित है, जो स्रोत फ़ाइल संशोधित होने पर पूरी तरह बैकएंड को फिर से निष्पादित करता है। मुझे किसी भी नुकसान का पता नहीं है; आप एक फ़ाइल को संशोधित करते हैं और सबकुछ बाद में दो या दो बार पुनः लोड किया जाता है। कुछ जो केवल "ज्यादातर" मामलों में काम करता है विकास के लिए बहुत बुरा है; आप बस सड़क पर दर्द से पीड़ित होने के लिए कह रहे हैं जब यह नहीं करता है। –

+0

डुप्लिकेट प्रश्न के कारण यहां पुनरीक्षण करना, और जोड़ना "ज़ोप का उपयोग करते समय पुनः लोड समय को कम करने का तरीका" अब तक सॉना.रलोड का उपयोग करना है (2013) – jsbueno

उत्तर

5

तो - इस का जवाब देता "मॉड्यूल जो किसी दिए गए पर निर्भर करते हैं की एक सूची खोजें एक "- इसके बजाय प्रश्न को अंततः कैसे phrased किया गया था - जो मैंने ऊपर जवाब दिया।

जैसा कि यह पता चला है, यह थोड़ा और जटिल है: किसी को सभी लोड मॉड्यूल के लिए निर्भरता पेड़ ढूंढना है, और प्रत्येक मॉड्यूल के लिए इसे उलटा करना है, जबकि लोडिंग ऑर्डर को सुरक्षित करना, जो चीज़ों को तोड़ नहीं देगा।

मैं भी पर ब्राज़ीलियाई के अजगर विकी को यह था: http://www.python.org.br/wiki/RecarregarModulos

#! /usr/bin/env python 
# coding: utf-8 

# Author: João S. O. Bueno 
# Copyright (c) 2009 - Fundação CPqD 
# License: LGPL V3.0 


from types import ModuleType, FunctionType, ClassType 
import sys 

def find_dependent_modules(): 
    """gets a one level inversed module dependence tree""" 
    tree = {} 
    for module in sys.modules.values(): 
     if module is None: 
      continue 
     tree[module] = set() 
     for attr_name in dir(module): 
      attr = getattr(module, attr_name) 
      if isinstance(attr, ModuleType): 
       tree[module].add(attr) 
      elif type(attr) in (FunctionType, ClassType):   
       tree[module].add(attr.__module__) 
    return tree 


def get_reversed_first_level_tree(tree): 
    """Creates a one level deep straight dependence tree""" 
    new_tree = {} 
    for module, dependencies in tree.items(): 
     for dep_module in dependencies: 
      if dep_module is module: 
       continue 
      if not dep_module in new_tree: 
       new_tree[dep_module] = set([module]) 
      else: 
       new_tree[dep_module].add(module) 
    return new_tree 

def find_dependants_recurse(key, rev_tree, previous=None): 
    """Given a one-level dependance tree dictionary, 
     recursively builds a non-repeating list of all dependant 
     modules 
    """ 
    if previous is None: 
     previous = set() 
    if not key in rev_tree: 
     return [] 
    this_level_dependants = set(rev_tree[key]) 
    next_level_dependants = set() 
    for dependant in this_level_dependants: 
     if dependant in previous: 
      continue 
     tmp_previous = previous.copy() 
     tmp_previous.add(dependant) 
     next_level_dependants.update(
      find_dependants_recurse(dependant, rev_tree, 
            previous=tmp_previous, 
            )) 
    # ensures reloading order on the final list 
    # by postponing the reload of modules in this level 
    # that also appear later on the tree 
    dependants = (list(this_level_dependants.difference(
         next_level_dependants)) + 
        list(next_level_dependants)) 
    return dependants 

def get_reversed_tree(): 
    """ 
     Yields a dictionary mapping all loaded modules to 
     lists of the tree of modules that depend on it, in an order 
     that can be used fore reloading 
    """ 
    tree = find_dependent_modules() 
    rev_tree = get_reversed_first_level_tree(tree) 
    compl_tree = {} 
    for module, dependant_modules in rev_tree.items(): 
     compl_tree[module] = find_dependants_recurse(module, rev_tree) 
    return compl_tree 

def reload_dependences(module): 
    """ 
     reloads given module and all modules that 
     depend on it, directly and otherwise. 
    """ 
    tree = get_reversed_tree() 
    reload(module) 
    for dependant in tree[module]: 
     reload(dependant) 

यह wokred सभी परीक्षणों मैं यहाँ बनाया में अच्छी तरह से - लेकिन मैं इसे कोस recoment नहीं होता। लेकिन कोड की कुछ पंक्तियों को संपादित करने के बाद एक चल रहे zope2 सर्वर को अद्यतन करने के लिए, मुझे लगता है कि मैं इसे स्वयं उपयोग करूँगा।

+0

हाय, मुझे लगा कि बस मॉड्यूलटाइप विशेषताओं की तलाश में है डीआईआर (मॉड्यूल) काफी अच्छा नहीं है। आयात कई बार xyz आयात abc'' जैसा दिखता है। इसे संभालने के लिए, किसी को डीआईआर (मॉड्यूल) सूची में फ़ंक्शनटाइप और क्लासटाइप विशेषताओं पर विचार करना चाहिए और उन लोगों के लिए, किसी को अपने संबंधित गेटैटर (एटीआर, '__module__') को पिकअप करना चाहिए और उन्हें –

+0

पर निर्भरता में जोड़ना चाहिए। मुझे इसे ठीक करना होगा - या दोनों जगहों से कोड को हटा देना होगा - यह इतना compelx है कि इसे किसी भी व्यक्ति के लिए काम करने के लिए "है" यह – jsbueno

+0

* फिक्स्ड * पोस्ट किया गया उदाहरण। – jsbueno

3

आप इयान Bicking के पेस्ट reloader मॉड्यूल है, जो करता है जो आप पहले से ही चाहते हैं पर एक नज़र लेने के लिए चाहते हो सकता है:

http://pythonpaste.org/modules/reloader?highlight=reloader

यह आप विशेष रूप से निर्भर फ़ाइलों की एक सूची नहीं दे करता है (जो केवल है तकनीकी रूप से संभव है यदि पैकेजर मेहनती और उचित रूप से निर्दिष्ट निर्भरता रहा है), लेकिन कोड को देखते हुए आपको प्रक्रिया को पुनरारंभ करने के लिए संशोधित फ़ाइलों की एक सटीक सूची मिल जाएगी।

2

बचाव के लिए कुछ आत्मनिरीक्षण:

from types import ModuleType 

def find_modules(module, all_mods = None): 
    if all_mods is None: 
     all_mods = set([module]) 
    for item_name in dir(module): 
     item = getattr(module, item_name) 
     if isinstance(item, ModuleType) and not item in all_mods: 
      all_mods.add(item) 
      find_modules(item, all_mods) 
    return all_mods 

यह आप सभी लोड मॉड्यूल के साथ एक सेट देता है - सिर्फ एक एकमात्र पैरामीटर के रूप में अपना पहला मॉड्यूल फ़ंक्शन को कॉल करें। फिर आप यह पुन: लोड जिसके परिणामस्वरूप सेट पर पुनरावृति सकता है, बस के रूप में के रूप में: [find_modules में मीटर के लिए पुनः लोड (एम) (< मॉड्यूल >)]

+0

बस इस कोड को समझने की कोशिश कर रहा है। - किसी दिए गए मॉड्यूल x से शुरू करें - मॉड्यूल का एक खाली सेट बनाएं जो x द्वारा आयात किया गया है - मॉड्यूल के लिए होने वाली सभी वस्तुओं की पहचान करने के लिए डीआईआर (x) पर पुनरावृत्त - उन्हें मॉड्यूल के सेट में जोड़ें एक्स - x के लिए सभी निर्भरताओं को खोजने के लिए यह रिकर्सिवली करें, मुझे शायद इसके साथ शुरू करने की आवश्यकता होगी और एक विशिष्ट मॉड्यूल –

+0

गह पर निर्भर सभी मॉड्यूल के सेट की पहचान करने के लिए एक रिवर्स मैपिंग प्राप्त करने की आवश्यकता होगी, आप ऐसा क्यों करेंगे? sys.modules में पहले से ही सभी लोड मॉड्यूल शामिल हैं .... –

+0

रुको - क्या आपको "मॉड्यूल की सूची" मॉड्यूल की सूची "पाइथन में निर्भर करती है" या एक विशिष्ट मॉड्यूल पर निर्भर सभी मॉड्यूल की सूची "की आवश्यकता है? मैं बाद में कोड के साथ आ सकता हूं, इस से अधिक जटिल नहीं - लेकिन सवाल पूर्व के लिए phrased है। – jsbueno