source

파이썬: 'from X import Y'로 가져온 구성 요소 Y를 다시 로드하시겠습니까?

manycodes 2023. 9. 23. 22:50
반응형

파이썬: 'from X import Y'로 가져온 구성 요소 Y를 다시 로드하시겠습니까?

파이썬에서 인터프리터 세션에서 모듈 X를 가져오면 다음을 사용하여import X, 외부에서 모듈이 변경되면 모듈을 다시 로드할 수 있습니다.reload(X). 그러면 제 통역 세션에서 변경 내용을 확인할 수 있습니다.

모듈 X에서 부품 Y를 가져올 때도 이것이 가능한지 궁금합니다.from X import Y.

성명서reload YY는 모듈 자체가 아니라 모듈 내부의 구성 요소(이 경우 클래스)이기 때문에 작동하지 않습니다.

인터프리터 세션을 떠나지 않고(또는 모듈 전체를 가져오는) 모듈의 개별 구성 요소를 다시 로드할 수 있습니까?

편집:

명확하게 설명하기 위해, 문제는 패키지 X에서 모듈 Y가 아닌 모듈 X에서 클래스 또는 함수 Y를 가져오고 변경 시 다시 로드하는 것입니다.

정답.

내 시험에서, 표시된 답은 단순한 것을 암시합니다.reload(X), 작동하지 않습니다.

정확한 대답은 다음과 같습니다.

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y

시험

제 시험은 다음과 같습니다(Python 2.6.5 + bpython 0.9.5.2).

X.py :

def Y():
    print "Test 1"

bpython:

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after

Y가 모듈이고 X가 패키지인 경우reload(Y)그렇지 않으면 좋은 Python 스타일 가이드(예: 제 고용주)가 모듈 에는 어떤 것도 가져오지 말라고 말하는 이유를 알게 될 것입니다. (이것은 여러 가지 훌륭한 이유 중 하나이지만, 사람들은 아무리 좋은 생각이 아니라고 설명해도 여전히 기능과 클래스를 직접 가져옵니다;-).

from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func

일단, 만약 피할 수 있다면, 재장전을 전혀 사용하지 말아야 합니다.하지만 여러분의 이유(즉, IDLE 내부 디버깅)가 있다고 가정해 보겠습니다.

라이브러리를 다시 로드해도 이름이 모듈의 네임스페이스로 다시 연결되지 않습니다.이렇게 하려면 변수만 다시 할당하면 됩니다.

f = open('zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()

from zoo import snakes
print snakes

f = open('zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()

import zoo
reload(zoo)
snakes = zoo.snakes # the variable 'snakes' is now reloaded

print snakes

몇 가지 다른 방법으로 할 수 있습니다.로컬 네임스페이스를 검색하고 문제가 된 모듈에서 가져온 모든 것을 재할당하여 프로세스를 자동화할 수 있지만, 우리는 충분히 악의적이라고 생각합니다.

만약 당신이 목성 환경에서 일을 하고 있다면, 당신은 이미from module import function마법의 기능을 사용할 수 있고,autoreload타고

%load_ext autoreload
%autoreload
from module import function

도입부.autoreload아이피톤은 여기에 주어집니다.

이 작업을 수행하려면:

from mymodule import myobject

대신 이렇게 하십시오.

import mymodule
myobject=mymodule.myobject

이제 내 개체를 계획했던 것과 동일한 방식으로 사용할 수 있습니다(모든 곳에서 읽을 수 없는 내 모듈 참조 없이).

대화형 작업을 하고 있고 내 모듈에서 내 개체를 다시 로드하려면 이제 다음을 사용할 수 있습니다.

reload(mymodule)
myobject=mymodule.myobject

당신이 사용했다고 가정할 때from X import Y, 다음 두 가지 옵션이 있습니다.

reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module

아니면

Y=reload(sys.modules['X']).Y

몇 가지 고려 사항:

A. 가져오기 범위가 모듈 전체가 아닌 경우(예: 함수로 가져오기) - 두 번째 버전을 사용해야 합니다.

에서 로 가져온 - 로드하고 로드하고 로드하는 B ). Y를 다른 모듈(Z)에서 X로 가져온 경우 - Z를 다시 로드하고 X를 다시 로드하고 모듈을 다시 로드하고 모든 모듈을 다시 로드하는 경우(예: 사용)[ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]하기 전에 로드할 수 의 값을 고치지 Z 를 에 X 를 Y 를 합니다.

  1. reload()eX,
  2. reload()gYX.

다시 로드해도 이미 생성된 다른 네임스페이스에 바인딩된 개체는 변경되지 않습니다(알렉스의 스타일 가이드를 따르더라도).

알렉스 마르텔리와 캣츠쿨의 답변을 따라가기 위해, 혼동되는 것처럼 보이는 정말 간단하지만 고약한 사례들이 있습니다.reload 2 에서는.

다음과 같은 소스 트리가 있다고 가정합니다.

- foo
  - __init__.py
  - bar.py

다음의 내용을 포함하여:

init.py :

from bar import Bar, Quux

bar.py :

print "Loading bar"

class Bar(object):
  @property
  def x(self):
     return 42

class Quux(Bar):
  object_count = 0
  def __init__(self):
     self.count = self.object_count
     self.__class__.object_count += 1
  @property
  def x(self):
     return super(Quux,self).x + 1
  def __repr__(self):
     return 'Quux[%d, x=%d]' % (self.count, self.x)

은 합니다를 잘 합니다.reload:

>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]

하지만 재장전을 시도해도 아무런 효과가 없거나 물건을 손상시킵니다.

>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module 'foo' from 'foo\__init__.pyc'>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module 'foo.bar' from 'foo\bar.pyc'>
>>> Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8

할 수 bar되었습니다.reload(foo.bar); 내가 재장전된 것에 접근할 수 있는 유일한 방법.Quux이지만,foo다를 있었습니다.Quux체,입니다를 일 것입니다.from bar import Bar, Quux 아닌import bar를 이어dQuux = bar.Quux 나아가 );Quux수업이 자기 자신과 맞지 않게 된 것은 이상한 일입니다.

언급URL : https://stackoverflow.com/questions/1739924/python-reload-component-y-imported-with-from-x-import-y

반응형