2009-12-01 2 views
10

파이썬 기반 웹 응용 프로그램의 개발 시간을 줄이기 위해 최근에 수정 한 모듈에 reload()를 사용하려고합니다. reload()는 최근 수정 된 모듈을 나열하는 전용 웹 페이지 (웹 응용 프로그램 개발 버전의 일부)를 통해 발생합니다 (py 파일의 수정 된 타임 스탬프는 해당 pyc 파일보다 나중입니다). 모듈의 전체 목록은 sys.modules에서 가져옵니다 (그리고 필자는 패키지에 포함 된 모듈에만 초점을 맞추기 위해 목록을 필터링합니다).파이썬의 특정 모듈에 의존하는 모듈 목록을 찾는 방법

개별 파이썬 파일을 다시로드하는 것이 경우에 따라 작동하는 것으로 보이고 다른 경우에는 작동하지 않는 것 같습니다. 나는 수정 된 모듈에 의존하는 모든 모듈을 다시로드해야하며 재로드가 적절한 순서로 이루어져야한다고 생각합니다.

특정 모듈에서 가져온 모듈 목록을 가져 오는 방법을 찾고 있습니다. 파이썬에서 이러한 종류의 인트로 스펙 션을 수행 할 수있는 방법이 있습니까?

내 접근 방식이 100 % 보장되지 않을 수도 있고 가장 안전한 방법은 모든 것을 다시로드하는 것이지만 대부분의 경우 빠른 접근 방식이 효과적이면 개발 목적으로는 충분할 것이라고 생각합니다. 장고 autoreloader

@Glenn 메이 나드, 고맙습니다에 대한 의견을

응답, 나는 장고의 autoreloader에 대해 읽어했다. 내 웹 응용 프로그램은 Zope 3을 기반으로하고 패키지의 양과 ZCML 기반의 초기화로 인해 데이터베이스 크기가 더 커지면 전체 재시작이 약 10 초에서 30 초 또는 그 이상 걸립니다. 다시 시작하는 동안이 시간을 절약하려고합니다. 내가 많은 변화를 겪었다 고 느낄 때, 나는 보통 전체 재시작을 선호하지만, 더 자주 나는 너무 많은 시간을 보내고 싶지 않은 곳에서 몇 줄의 선을 바꾸고있다. 개발 설정은 프로덕션 설정과 완전히 독립적이며, 일반적으로 다시로드 할 때 문제가 발생하면 응용 프로그램 페이지에서 비논리적 인 정보가 표시되거나 예외가 발생하기 시작하므로 명확 해집니다. 선택적 재 장전이 효과가 있는지 아닌지에 대해 매우 관심이 많습니다.

당신은 이미 원하는 것을 이안 Bicking의 붙여 넣기 장전 모듈, 한 번 봐 걸릴 수도 있습니다
+0

Django의 자동 로더와 같이 소스 파일을 수정할 때 백엔드를 완전히 다시 실행하는 것이 훨씬 안전합니다. 나는 어떤 불리한 점도 모른다. 파일을 수정하면 모든 내용이 자동으로 두 번째 또는 두 번째로 다시로드됩니다. "대부분의"경우에만 효과가있는 것은 개발에 매우 ​​나쁜 것입니다. 당신은 단지 길 아래로 고통스럽게 물지 않도록 요구하고 있습니다. –

+0

중복 된 질문으로 인해 여기서 다시 살펴보고 "zope을 사용할 때 재로드 시간을 최소화하는 방법"은 sauna.reload now (2013) – jsbueno

답변

5

그래서 -이 주어진에 따라 모듈의 목록을 찾아 "답변 하나 "- 질문이 처음에 어떻게 표현 되었는가보다 - 나는 위에서 답했다.

이것은 다소 복잡합니다.로드 된 모든 모듈에 대한 종속성 트리를 찾아서 각 모듈에 대해 반전시켜야하며,로드 순서를 유지하면서 물건을 손상시키지 않아야합니다.

나는 또한에 브라질의의 파이썬 위키이 게시했다 : 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

안녕하세요, 저는 ModuleType 속성을 찾고 있습니다. dir (module)은 충분하지 않다. import가''from xyz import abc'와 같이 여러 번 나타난다. 이것을 처리하기 위해, dir (module) 목록에있는 FunctionType과 ClassType 속성을 고려해야하며, 하나는 해당 getattr (attr, '__module__')을 픽업하여 종속성에 추가해야합니다 . –

+0

사실 저는 그것을 수정해야합니다 - 또는 두 위치에서 코드를 제거해야합니다 - 이제는 강제로 필요로하는 누구든지 작업 할 수 있습니다 – jsbueno

+0

* FIXED * 게시 된 예제 – jsbueno

3

:

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에서 m에 다시로드 (m) (> < 모듈)]

+0

을 사용하는 것입니다.이 코드를 이해하려고합니다. - 주어진 모듈로 시작 x - x 으로 가져온 빈 모듈 집합 생성 - 모듈이 될 모든 항목을 식별하기 위해 -이를 모듈 집합에 추가합니다. x - 이것을 반복적으로 수행하여 x에 대한 모든 종속성을 찾으십시오. 아마도이 모듈로 시작하여 특정 모듈에 종속 된 모든 모듈 집합을 식별하기 위해 역 매핑을 수행해야합니다. –

+0

Gah, 왜이 작업을 수행할까요? sys.modules에는 이미로드 된 모듈이 모두 포함되어 있습니다. ... –

+0

기다리십시오 - "모듈이 파이썬에 의존하는 모듈 목록"또는 "특정 모듈에 종속 된 모든 모듈 목록"이 필요합니까? 나중에 코드를 생각해 낼 수 있습니다.이 코드는이 코드보다 훨씬 복잡하지는 않지만 - 질문은 구 코드에 대한 것입니다. – jsbueno

관련 문제