[python] 모듈을 언로드 (다시로드)하려면 어떻게합니까?

오래 실행되는 Python 서버가 있으며 서버를 다시 시작하지 않고 서비스를 업그레이드하고 싶습니다. 가장 좋은 방법은 무엇입니까?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()



답변

reload내장 함수 를 사용하여 이미 가져온 모듈을 다시로드 할 수 있습니다 (Python 3.4+ 만 해당) .

from importlib import reload
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

파이썬 3에서는 모듈 reload로 옮겨졌습니다 imp. 3.4에서는 imp찬성이 사용됩니다 importlib, 그리고 reload후자에 추가되었습니다. 3 이상을 대상으로하는 경우 호출 reload하거나 가져올 때 적절한 모듈을 참조하십시오 .

나는 이것이 당신이 원하는 것이라고 생각합니다. Django의 개발 서버와 같은 웹 서버는이를 사용하여 서버 프로세스 자체를 다시 시작하지 않고도 코드 변경의 영향을 볼 수 있습니다.

문서에서 인용하려면 :

파이썬 모듈의 코드가 다시 컴파일되고 모듈 수준 코드가 다시 실행되어 모듈 사전의 이름에 바인딩되는 새로운 객체 집합을 정의합니다. 확장 모듈의 초기화 기능은 두 번째로 호출되지 않습니다. 파이썬의 다른 모든 객체와 마찬가지로 이전 객체는 참조 횟수가 0으로 떨어진 후에 만 ​​재생됩니다. 모듈 네임 스페이스의 이름은 새로운 객체 또는 변경된 객체를 가리 키도록 업데이트됩니다. 이전 개체에 대한 다른 참조 (예 : 모듈 외부의 이름)는 새 개체를 참조하기 위해 리 바인드되지 않으며 원하는 경우 각 네임 스페이스에서 업데이트되어야합니다.

질문에서 언급했듯이 클래스가 모듈 에 Foo있으면 객체 를 재구성 Foo해야 foo합니다.


답변

Python 3.0–3.3에서는 다음을 사용합니다. imp.reload(module)

BDFL는대답 이 질문을.

그러나 @Stefan 덕분 imp에 3.4에서 더 이상 사용되지 않습니다 importlib. ).

나는 생각한다 그러므로 당신이 지금 사용하는 거라고, importlib.reload(module)잘 모르겠어요하지만,.


답변

순수한 파이썬이 아닌 경우 모듈을 삭제하는 것이 특히 어려울 수 있습니다.

가져온 정보는 어떻게 삭제합니까?

sys.getrefcount ()를 사용하여 실제 참조 수를 찾을 수 있습니다.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

3보다 큰 숫자는 모듈을 제거하기 어렵다는 것을 나타냅니다. 자체 개발 한 “빈”(아무것도 포함) 모듈은 다음에 가비지 수집되어야합니다.

>>> del sys.modules["empty"]
>>> del empty

세 번째 참조는 getrefcount () 함수의 아티팩트이므로


답변

reload(module)그러나 완전히 독립형 인 경우에만 가능합니다. 다른 것이 모듈 (또는 모듈에 속하는 객체)에 대한 참조가 있으면 이전 코드가 예상보다 오래 걸려서 미묘하고 호기심 많은 오류가 발생합니다.isinstance 합니다. 같은 코드.

단방향 종속성이있는 경우 이전 코드에 대한 모든 참조를 제거하려면 다시로드 된 모듈에 종속 된 모든 모듈을 다시로드해야합니다. 그런 다음 재로드 된 모듈에 의존하는 모듈을 재귀 적으로 다시로드하십시오.

예를 들어 패키지 재로드를 처리 할 때 매우 일반적인 순환 종속성이있는 경우 그룹의 모든 모듈을 한 번에 언로드해야합니다. 당신은 이것을 할 수 없습니다reload()종속성을 새로 고치기 전에 각 모듈을 다시 가져 와서 이전 참조가 새 모듈로 들어올 수 있기 때문에이 .

이 경우이를 수행하는 유일한 방법은 해킹 sys.modules하는 것입니다. sys.modules다음 가져올 때 다시로드 할 각 항목을 살펴보고 삭제 None해야하며 실패한 상대 가져 오기 캐싱과 관련된 구현 문제를 처리 해야하는 값을 가진 항목도 삭제해야합니다 . 별로 좋지는 않지만 코드베이스 외부에 참조를 남기지 않는 완전히 독립적 인 종속성 세트가있는 한 실행 가능합니다.

서버를 다시 시작하는 것이 가장 좋습니다. 🙂


답변

if 'myModule' in sys.modules:
    del sys.modules["myModule"]


답변

Python 2의 경우 내장 함수 reload ()를 사용하십시오 .

reload(module)

Python 2 및 3.2–3.3의 경우 모듈 imp에서 다시로드를 사용하십시오 .

import imp
imp.reload(module)

그러나 importlib에 찬성하여 버전 3.4부터 imp 더 이상 사용되지 않으므로 다음을 사용하십시오.

import importlib
importlib.reload(module)

또는

from importlib import reload
reload(module)


답변

다음 코드는 Python 2/3 호환성을 허용합니다.

try:
    reload
except NameError:
    # Python 3
    from imp import reload

reload()두 버전 모두 에서처럼 사용할 수 있으므로 작업이 더 간단 해집니다.