2009-07-17 4 views
1

파이썬에서 동적 인 리로딩 객체를 구현하려고합니다. 코드 변경 내용을 반영합니다.파이썬 객체 트리를 가로 질러

모듈 리로딩이 작동하지만 변경 사항이 적용되도록 모듈 클래스의 모든 인스턴스를 다시 만들어야합니다.

문제는 개체 데이터 (개체 __dict__ 콘텐츠)가 처리 중에 손실된다는 것입니다.

그래서 나는 또 다른 접근 시도 :

def refresh(obj, memo=None): 
    if memo is None: 
     memo = {} 
    d = id(obj) 
    if d in memo: 
     return 
    memo[d] = None 
    try: 
     obj.__class__ = getattr(sys.modules[obj.__class__.__module__], 
       obj.__class__.__name__) 
    except TypeError: 
     return 
    for item in obj.__dict__.itervalues(): 
     if isinstance(item, dict): 
      for k, v in item.iteritems(): 
       refresh(k, memo) 
       refresh(v, memo) 
     elif isinstance(item, (list, tuple)): 
      for v in item: 
       refresh(v, memo) 
     else: 
      refresh(item, memo) 

을 그리고 놀랍게도 작동한다! 내 객체에서 refresh()를 호출 한 후 새 코드를 다시 만들지 않고도 효과가 있습니다.

하지만 이것이 올바른 방법으로 객체를 통과하는지 확신 할 수 없습니까? 객체의 컴포넌트를 트래버스하는 더 좋은 방법이 있습니까?

답변

1

파이썬 쿡북에있는 this recipe을 참조하십시오. (실제로는 Google 도서 검색으로 실제로 읽을 수 있다고 믿는 "인쇄 된"버전의 더 나은 버전 일 수도 있고 O'Reilly의 "Safari"사이트에서 무료 1 주 평가판 구독 - "인쇄 된 책"버전을 받으려면 허드슨의 독창적 인 요리법을 편집했습니다!).

+0

이것은 내가 채택한 솔루션과 매우 비슷합니다 (일부 "최상위 레벨"클래스는 래핑되어 인스턴스를 다시로드 할 수 있도록 추적합니다). 문제는 내 패키지에있는 모든 클래스를 래핑하고 싶지 않다는 것입니다 (또는 예제 에서처럼 클래스를 다시로드하는 것부터 상속받습니다). 최상위 클래스 만 상속합니다. 이것이 객체 트리 트래버스 기능이 필요한 이유입니다. –

+0

나는 당신이 완전한 보편성으로 그것을 할 수 없다고 믿습니다. __slots__ 및 기타 메타 클래스 기능을 사용하는 경우 Python 객체가이를 지원하지 않도록 코딩 될 수 있습니다 (확장 코드, 가비지 콜렉션 탐색, weakrefs, pickling/unpickling 및 & c) 특정 지원이 필요한 이유입니다. 열린 파일, DB 연결, 생성기 개체, 잠금 장치 ... 일부 부품이 누락 될 위험이 있다면 최소한 세트, deques, default_factory defaultdfactory 멤버 등을 커버해야합니다. –

+0

그렇다면 방금 가지고 있습니다. 내 반복 설정에서 더 많은 유형 테스트를 추가하십시오. has_sequence_interface/has_mapping_interface() 함수를 사용하여 객체를 반복 할 수있는 방법을 테스트하는 것이 좋을 것입니다. –

0

파이썬 코드를 다시로드하기 위해 필자는 오래 전에이 구현을 생각해 냈습니다.

http://www.codexon.com/posts/a-better-python-reload

아마 가능한 가장 빠르고 가장 깨끗한 방법입니다.

+0

코드가 내 작품과 작동하지 않습니다 ("AttributeError : __provides__"오류가 발생합니다. zope.interface와 잘 작동하지 않는다고 생각합니다). 게다가 인스턴스 내에서 인스턴스를 다시로드 할 수 있다고 생각하지 않습니다. 이것이 내가 달성하고자하는 작업입니다. –

+0

다른 리로더와 인터페이스하기위한 것이 아닙니다. 인스턴스 내에서 인스턴스를 다시로드하는 경우 인스턴스 대신 클래스를 변경하므로 인스턴스를 다시로드 할 필요가 없습니다. 인스턴스에서 호출 된 메소드는 자동으로 새 클래스로 전송됩니다. – Unknown

+0

재로드해야하는 모듈에서 reload() 함수를 실행하기 만하면 모든 재로드 코드를 비활성화했습니다. 죄송합니다. 나는 그것이 무엇을하는지 이해하지 못했고, 시간이되면 문제를 디버그하려고 노력할 것입니다. –

관련 문제