Programing

Python : 'from X import Y'로 가져온 컴포넌트 Y를 다시로드 하시겠습니까?

lottogame 2020. 10. 10. 09:31
반응형

Python : 'from X import Y'로 가져온 컴포넌트 Y를 다시로드 하시겠습니까?


Python에서를 사용하여 인터프리터 세션에서 모듈 X를 가져 왔고 모듈 import X이 외부에서 변경되면 reload(X). 그러면 내 통역 세션에서 변경 사항을 사용할 수 있습니다.

을 사용하여 모듈 X에서 구성 요소 Y를 가져올 때도 이것이 가능한지 궁금합니다 from X import Y.

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

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

편집하다:

설명을 위해 질문은 모듈 X 에서 클래스 또는 함수 Y가져 와서 패키지 X에서 모듈 Y가 아니라 변경시 다시로드하는 것입니다.


Y는 모듈 (그리고 X 패키지)하면 reload(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

우선 재 장전을 피할 수 있다면 전혀 사용하지 말아야합니다. 하지만 이유가 있다고 가정 해 봅시다 (예 : 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 modulename import func

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

이렇게하려면 다음을 수행하십시오.

from mymodule import myobject

대신 다음을 수행하십시오.

import mymodule
myobject=mymodule.myobject

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

대화식으로 작업 중이고 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로 가져온 경우-X를 다시로드하고 모듈을 다시로드하는 것보다 Z를 다시로드해야합니다. 모든 모듈을 다시로드 (예 : using [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]) 하더라도 Z를 다시로드하기 전에 X를 다시로드 할 수 있습니다. Y 값을 새로 고치지 마십시오.


  1. reload()모듈 X,
  2. reload()가져 오기 모듈 Y에서 X.

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


경우 당신은 jupyter 환경에서 최선을 다하고, 당신은 이미 from module import function, 마법 기능을 사용할 수 있습니다 autoreload에 의해

%load_ext autoreload
%autoreload
from module import function

autoreloadin IPython 의 소개는 여기에 있습니다 .


Just to follow up on AlexMartelli's and Catskul's answers, there are some really simple but nasty cases that appear to confound reload, at least in Python 2.

Suppose I have the following source tree:

- foo
  - __init__.py
  - bar.py

with the following content:

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)

This works just fine without using reload:

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

But try to reload and it either has no effect or corrupts things:

>>> 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

The only way I could ensure the bar submodule was reloaded was to reload(foo.bar); the only way I access the reloaded Quux class is to reach in and grab it from the reloaded sub module; but the foo module itself kept holding onto the original Quux class object, presumably because it uses from bar import Bar, Quux (rather than import bar followed by Quux = bar.Quux); furthermore the Quux class got out of sync with itself, which is just bizarre.

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

반응형